Skip to content

Allow normal Swift default property initialization syntax #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 23, 2020
Merged

Allow normal Swift default property initialization syntax #170

merged 19 commits into from
Jun 23, 2020

Conversation

MPLew-is
Copy link
Contributor

@MPLew-is MPLew-is commented May 30, 2020

This change allows the normal var foo = "blah" default initialization syntax for Options, as a parallel initialization method as using the default parameter.

This syntax may feel more natural to some developers (myself included), but does not break any existing code using the original initialization method.

Checklist

  • I've added at least one test that validates that my change is working, if appropriate
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary

This change allows the normal `var foo = "blah"` default initialization 
syntax for `Option`s, as a parallel initialization method as using the 
`default` parameter.
@MPLew-is
Copy link
Contributor Author

I've tested this with this simple change, and it seems to work as expected (and all the test cases still pass locally); however, I want to make sure this is something that would be desired before continuing to extend this to the other parameter types.

@MPLew-is
Copy link
Contributor Author

MPLew-is commented May 30, 2020

A simple implementation to test:

import ArgumentParser

struct SomeCli: ParsableCommand {
	@Option
	var data: String = "test"

	func run() throws {
		print(data)
	}
}

SomeCli.main()
$ swift run cli
test
$ swift run cli --data=test2
test2

@natecook1000
Copy link
Member

@swift-ci Please test

@MPLew-is
Copy link
Contributor Author

Looks like everything passed in CI, so is this something that would be desired for the remaining parameter types?

@natecook1000
Copy link
Member

Thanks for starting this implementation! It’s been on my to-do list to investigate, but I apparently hadn’t opened an issue. I have a couple in-flight changes that you might want to wait for, most notably removing ExpressibleByArgument conformance for Optional, which will change the list of inits for @Argument and @Option. I’ll try to get that in so you can keep moving forward with this.

The biggest downside I see to this change is that it can effectively double the number of inits in some cases, where the default: Value? = nil parameter needs to be replaced by two separate inits (one with a wrappedValue parameter and one without). That said, I think the improved syntax is worth it as long as type checking/etc still works out.

@MPLew-is
Copy link
Contributor Author

Given those concerns, would it maybe make sense to drop the current default: syntax entirely, assuming that this change works as I intend it to? I realize it would break a lot of existing usage, but this is also in very early development so it may be the best time to do it if you feel this syntax is an improvement over the current one.

And honestly I’ll probably push ahead with the development on this more just as an exercise for myself, so don’t rush your other changes on my account; once they’re done, I can always integrate them back into this.

@kylemacomber
Copy link

I think this is a great direction

@natecook1000
Copy link
Member

natecook1000 commented Jun 8, 2020

Given those concerns, would it maybe make sense to drop the current default: syntax entirely, assuming that this change works as I intend it to? I realize it would break a lot of existing usage, but this is also in very early development so it may be the best time to do it if you feel this syntax is an improvement over the current one.

I definitely agree that we'd just want the one syntax long term. To help existing users transition, we'll want to go from the status quo to three different inits:

// current
init(default: Value? = nil, ...)

// new
init(wrappedValue: Value, ...)
init(...)
@available(*, deprecated, message: "Use regular property initialization for default values")
init(default: Value?, ...)

There's ample room for code deduplication in the initializers, but that can come after this change.

And honestly I’ll probably push ahead with the development on this more just as an exercise for myself, so don’t rush your other changes on my account; once they’re done, I can always integrate them back into this.

That change landed in #173, so you've got a clear field for this. Thanks again!

MPLew-is added 7 commits June 13, 2020 23:36
Preparing for another no-initial value `init` to be added and the existing one with a `default` parameter to be deprecated
It's replaced with an `init` containing no default value parameter, which will be used when the user does not provide any value.

Also add a (most likely unnecessary) sanity test to make sure initializations without a default value still work.
Also copy out documentation to allow clean removal of the older `init` when the time comes.
@MPLew-is
Copy link
Contributor Author

I'll continue work on this tomorrow/over the next week, but I believe Options are now fully ready for review so please let me know if you have any feedback.

@john-mueller
Copy link
Contributor

I just submitted #186, which adds the default parameter to the last two initializers for Option and Argument (when value is an array), so those would have to be reworked as well. 😬

I like this direction for initialization over the default parameters.

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great, @MPLew-is! One note for you below, plus the documentation should read as if using the regular assignment syntax was always the way to do this — we'll handle the notes about old/new and migration in the changelog.

MPLew-is added 5 commits June 15, 2020 21:56
This mirrors the non-transform variants, and should have been included in the previous commits
Private `init` doesn't need defaults, and the deprecated public ones shouldn't have it to avoid confusion with the new methods
Treat new initializers as the originally intended way to allow for clean removal of the deprecated methods
Also add some additional documentation to the deprecated methods to help point users in the right direction
@MPLew-is MPLew-is requested a review from natecook1000 June 16, 2020 07:16
@MPLew-is
Copy link
Contributor Author

MPLew-is commented Jun 16, 2020

Other than the issue I've pointed out in a line comment, this should be functionally complete. I'll work on the high-level documentation next, but please let me know if you see any other changes I should make!

MPLew-is added 3 commits June 18, 2020 23:26
Prints a warning when that default value is `true` instead of `false`, as the flag value will be pinned regardless of user input
All examples and unit tests have been transitioned to the new syntax, with the exception of `SourceCompatEndToEndTests`, which should not have the old style removed until it is no longer valid source.
@MPLew-is MPLew-is marked this pull request as ready for review June 21, 2020 09:20
@MPLew-is
Copy link
Contributor Author

This should be ready for review, let me know if you find any issues!

@MPLew-is MPLew-is mentioned this pull request Jun 22, 2020
4 tasks
@natecook1000
Copy link
Member

This is looking great, @MPLew-is! I've reconciled changes with the array defaults addition in #186 — going to merge and then continue that integration. 🎉🎉

@natecook1000
Copy link
Member

@swift-ci Please test

1 similar comment
@natecook1000
Copy link
Member

@swift-ci Please test

@natecook1000
Copy link
Member

@swift-ci Please test Linux platform

@natecook1000 natecook1000 merged commit c0f9a5f into apple:master Jun 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants