> On Dec 21, 2015, at 5:47 PM, Chris Lattner via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> On Dec 21, 2015, at 11:32 AM, Matthew Johnson via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-Dave



_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to