> On Dec 21, 2015, at 5:47 PM, Chris Lattner via swift-evolution
> <[email protected]> wrote:
>
> On Dec 21, 2015, at 11:32 AM, Matthew Johnson via swift-evolution
> <[email protected] <mailto:[email protected]>> wrote:
>> I have completed a draft of the proposal I have been working on for flexible
>> memberwise initialization. I am really looking forward to your input and
>> will be refining the proposal based on our discussion.
>>
>> I am including a current snapshot of the proposal in this message. I will
>> keep the proposal up to date on Github at this link:
>>
>> https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md>
> This is a really really interesting approach, I really like it. Detailed
> comments below, I’m skipping all the stuff I agree with or have no additional
> comments on:
>
>>
>> Flexible Memberwise Initialization
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#replacing-the-current-memberwise-initializer>Replacing
>> the current memberwise initializer
>>
>> struct S {
>> let s: String
>> let i: Int
>>
>> // user declares:
>> memberwise init() {}
> It never occurred to me to allow a body on a memberwise initializer, but
> you’re right, this is a great feature. I love how this makes memberwise init
> behavior a modifier on existing initializers.
I’d be inclined to drop the “()” on these, though. It appears to imply an
empty parameter list is allowed, when it is not.
>> Properties with initial values
>>
>> struct S {
>> let s: String = "hello"
>> let i: Int = 42
>>
>> // user declares:
>> memberwise init() {}
>> // compiler synthesizes:
>> init(s: String = "hello", i: Int = 42) {
>> self.s = s
>> self.i = i
>> }
>> }
> In the case of let properties, I’m uncomfortable with this behavior and it
> contradicts our current init rules (the synthesized code isn’t legal).
> Please change the example to var properties, and then it’s can fit with the
> model :-).
>
> That said, I think the interaction of explicit initializers and memberwise
> initializers begs discussion. It would be a much simpler model to only get
> memberwise parameters for properties without an explicit init. Have you
> considered this model, what are the tradeoffs with allowing vars to overwrite
> them? Allowing an explicit init to be overwritten by the memberwise
> initializer seems potentially really confusing, and since you allow explicit
> arguments on inits, this could always be handled manually if someone really
> really wanted it. For example, they could write:
>
> memberwise init(s : String) {
> self.s = s
> }
>
> If they wanted to get the sugar of memberwise inits (presumably for other
> properties without an explicit init) but still allow one to be overwritten.
>
>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#partial-memberwise-initialization>Partial
>> memberwise initialization
>>
>> struct S {
>> let s: String
>> let i: Int
>>
>> // user declares:
>> memberwise init() {
>> i = getTheValueForI()
>> }
>> // compiler synthesizes (suppressing memberwise initialization for
>> properties assigned in the initializer body):
>> init(s: String) {
>> self.s = s
>> // body of the user's initializer remains
>> i = getTheValueForI()
>> }
>> }
> This doesn’t seem like the right behavior to me. The compiler shouldn’t be
> in the business of scanning the body of the init to decide what members are
> explicitly initialized. I’d suggest that the model simply be that the
> contents of the {} on a memberwise init get injected right after the
> memberwise initializations that are done. This mirrors how properties with
> default values work.
>
>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#lazy-properties-and-incompatible-behaviors>lazy
>> properties and incompatible behaviors
>>
>> struct S {
>> let s: String
>> lazy var i: Int = InitialValueForI()
>>
>> // user declares:
>> memberwise init() {
>> }
>> // compiler synthesizes:
>> init(s: String) {
>> self.s = s
>> // compiler does not synthesize initialization for i
>> // because it contains a behavior that is incompatible with
>> // memberwise initialization
>> }
>> }
> Yes, this is likely to be subsumed into JoeG’s "behaviors” proposal. In the
> meantime, I’d suggest no behavior change for lazy properties.
>
>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#nomemberwise-properties>@nomemberwise
>> properties
>>
>> struct S {
>> let s: String
>> @nomemberwise let i: Int
>>
>> // user declares:
>> memberwise init(configuration: SomeTypeWithAnIntMember) {
>> i = configuration.intMember
>> }
>> // compiler synthesizes:
>> init(configuration: SomeTypeWithAnIntMember, s: String) {
>> self.s = s
>> i = configuration.intMember
>> }
>> }
> @nomemberwise is an interesting extension, but since it is a pure extension
> over the basic model, I’d suggest moving this into a “possible future
> extensions” section. The proposal doesn’t need this feature to stand on its
> own.
>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#delegating-and-convenience-initializers>delegating
>> and convenience initializers
>>
>> struct S {
>> let s: String = "hello"
>> let i: Int = 42
>>
>> // user declares:
>> memberwise init() {}
>> // compiler synthesizes:
>> init(s: String = "hello", i: Int = 42) {
>> self.s = s
>> self.i = i
>> }
>>
>> // user declares:
>> memberwise init(describable: CustomStringConvertible) {
>> self.init(s: describable.description)
>> }
>> // compiler synthesizes (adding forwarded memberwise parameters):
>> init(describable: CustomStringConvertible, i: Int = 42) {
>> self.init(s: describable.description, i: i)
>> }
>> }
> This example is introducing two things: convenience inits, but also parameter
> arguments. For the sake of the proposal, I’d suggest splitting the parameter
> arguments out to its own discussion. It isn’t clear to me whether the
> memberwise initializers should come before explicit arguments or after, and
> it isn’t clear if we should require the developer to put something in the
> code to indicate that they exist. For example, I could imagine a syntax like
> this:
>
> memberwise init(…) {}
> memberwise init(describable: CustomStringConvertible, ...) {
>
> Where the … serves as a reminder that the init takes a bunch of synthesized
> arguments as well.
>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#subclass-initializers>subclass
>> initializers
>>
>> class Base {
>> let baseProperty: String
>>
>> // user declares:
>> memberwise init() {}
>> // compiler synthesizes:
>> init(baseProperty: String) {
>> self.baseProperty = baseProperty
>> }
>> }
>>
>> class Derived: Base {
>> let derivedProperty: Int
>>
>> // user declares:
>> memberwise init() {}
>> // compiler synthesizes (adding forwarded memberwise parameters):
>> init(baseProperty: String, derivedProperty: Int) {
>> self.derivedProperry = derivedProperty
>> super.init(baseProperty: baseProperty)
>> }
>> }
> This also seems unclear to me. We’re generally very concerned about tightly
> coupling derived classes to their bases (in an API evolution scenario, the
> two classes may be in different modules owned by different clients).
> Further, the base class may have multiple inits, and it wouldn’t be clear
> which one to get the arguments from.
>
>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#detailed-design>Detailed
>> design
>>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#syntax-changes>Syntax
>> changes
>>
>> This proposal introduces two new syntactic elements: the memberwise
>> initializer declaration modifier and the @nomemberwise property attribute.
>>
> As before, I’d suggest splitting @nomemberwise out to a “potential future
> extensions section”.
>
>> Algorithm
>>
>> The steps described in this section will be followed by the compiler when it
>> performs memberwise initialization synthesis. These steps supercede the
>> synthesis of initialization for properties with initial values that exists
>> today.
>>
>> When the compiler performs memberwise initialization synthesis it will
>> determine the set of properties that are eligible for synthesis that are not
>> directly initialized in the body of the initializer. It will then synthesize
>> parameters for them as well the initialization of them at the beginning of
>> the initializer body.
>>
> I’d strongly suggest considering a model where properties that have an
> explicit initializer don’t get a memberwise init.
>
> Have you considered whether computed properties make sense to loop into your
> model?
>
> Typo "initialzier”.
>
>>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#objective-c-class-import>Objective-C
>> Class Import
>>
>> Objective-C frameworks are extremely important to (most) Swift developers.
>> In order to provide the call-site advantages of flexible memberwise
>> initialization to Swift code using Cocoa frameworks this proposal recommends
>> introducing a MEMBERWISE attribute that can be applied to Objective-C
>> properties and initializers.
>>
> This is also an orthogonal extension on top of the base proposal. I’d
> suggest splitting it off to a “possible future extensions” section as well.
>
>>
>>
>> <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md#impact-on-existing-code>Impact
>> on existing code
>>
>> The changes described in this proposal are strictly additive and will have
>> no impact on existing code.
>>
>> One possible breaking change which may be desirable to include alongside
>> this proposed solution is to elimintate the existing memberwise initializer
>> for structs and require developers to specifically opt-in to its synthesis
>> by writing memberwise init() {}. A mechanical transformation is possible to
>> generate this declaration automatically if the existing memberwise
>> initializer is removed.
>>
> I think that that would be very interesting to discuss, but I lean towards
> keeping our existing model for synthesizing a memberwise init if there is no
> other init in a struct (and we should do it for classes as well). Requiring
> someone to write "memberwise init() {}” is just boilerplate, and producing it
> as “internal” avoids most of the problems from being something undesirable
> being generated. That said, I see the argument that being more explicit is
> good.
>
> Overall, I’m a huge fan of this proposal and the direction you’re going in.
>
> -Chris
>
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
-Dave
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution