> On Dec 26, 2015, at 11:31 PM, Chris Lattner <[email protected]> wrote:
> 
> On Dec 25, 2015, at 12:04 PM, Matthew Johnson <[email protected] 
> <mailto:[email protected]>> wrote:
>>>> Discussion on a couple of topics continues inline below as well.
>>> 
>>> Great, comments below:
>> 
>> Thanks for continuing the discussion.  I have updated the proposal to 
>> reflect the core functionality and moved everything else to the future 
>> enhancements section.  I think this draft is ready or nearly ready for a PR.
>> 
>> Here is a link to the current draft: 
>> https://github.com/anandabits/swift-evolution/edit/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md
>>  
>> <https://github.com/anandabits/swift-evolution/edit/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md>
>> 
>> Here is a link to the commit diff: 
>> https://github.com/anandabits/swift-evolution/commit/f15360d2e201709640f9137d86a8b705a07b5466?short_path=f5ec377#diff-f5ec377f4782587684c5732547456b70
>>  
>> <https://github.com/anandabits/swift-evolution/commit/f15360d2e201709640f9137d86a8b705a07b5466?short_path=f5ec377#diff-f5ec377f4782587684c5732547456b70>
> Thanks again for pushing this forward, this is looking great.

Sounds good.  I just submitted a PR.  I think it’s ready.  Please let me know 
if you feel any further changes are necessary.

> 
>>> It is also annoying that writing it as a static property would force you to 
>>> write something like “X.a" instead of just “a”.
>> 
>> I agree with this.  I can accept an argument that this provides enough value 
>> to avoid changing the language.
>> 
>> That said, I do think default values for let properties are higher value.  
>> If I had to pick one it would be default values and I would consider it to 
>> be worthy of a breaking change in the language.  But It would be great if we 
>> can find a way to support both.
> 
> I understand your desire, but this really is something we’ll have to discuss 
> carefully.  Changing Swift soft that “let x = 42” doesn’t necessarily mean 
> that x is 42 is a pretty deep semantic change, which will be surprising for 
> many people (as was noted by others on this thread).  I agree that it would 
> be great to get more flexible initialization for lets, but keep in mind that 
> you can already do this long-hand if you want.

I know changing the existing behavior would require very careful thinking.  I 
am absolutely open to any solution that allow a default value for let 
properties to be specified whether it changes the existing behavior or not.  
What is the best way I can help to move this discussion forward in a productive 
manner?  Would it be a good idea to start a new thread on the topic?  Or is 
this something you feel like the core team needs to mull over for a while 
before we can have a productive conversation on the list?

> 
>>> This I still have a concern with, in two ways:
>>> 
>>> 1) This still has tight coupling between the base and derived class.  
>>> Properties in a based class are not knowable by a derived class in general 
>>> (e.g. across module boundaries) and this directly runs afoul of our 
>>> resilience plans.  Specifically, across module boundaries, properties can 
>>> change from stored to computed (or back) without breaking clients.
>>> 
>>> 2) You’re introducing another unnecessary feature "super.init(…)” which 
>>> will have to be independently justified. 
>>> 
>> 
>> I will continue thinking about how this might be solved and also about other 
>> cases where such a forwarding feature might be useful.  
> 
> Sounds good.  This is definitely an interesting area to investigate, but I 
> don't want the general goodness of your base memberwise init proposal to have 
> to wait :-)

I agree with you on not holding back the base proposal.  

I really appreciate you noticing that this should really be orthogonal to the 
base proposal.  I’ve already been giving this a lot of thought.  It is very 
clear to me now that a much more general parameter / argument forwarding 
feature is the right approach.  I am going to pursue a proposal for that as 
well.

> 
>>> Other comments:
>>> 
>>> In "Impact on existing code”, given your proposal, I think that we should 
>>> keep the implicit memberwise initializer on classes, start generating it 
>>> for root classes, and generate it for derived classes whose parent has a DI 
>>> with no arguments (e.g. subclasses of NSObject).  We should keep the 
>>> current behavior where it is generated with internal behavior, and it is 
>>> surpressed if *any* initializers are defined inside of the type.
>> 
>> I’ll update that section to reflect these comments.  
>> 
>> One question I have is what the implicit memberwise initializer should do in 
>> the case of private members.  If we make it follow the rules of this 
>> proposal we would break existing structs with private members that are 
>> currently receiving the implicit memberwise initializer.  
>> 
>> I think this would be a good breaking change for both consistency with this 
>> proposal and because implicitly exposing private members via the initializer 
>> was a questionable choice.  A mechanical migration could generate code to 
>> add an explicit implementation of the previously implicit initializer that 
>> doesn’t qualify under the rules of the new proposal.  How do you feel about 
>> this?
> 
> I don’t have a strong opinion about this, and I can see reasonable arguments 
> on either side.  Breaking source compatibility in this case isn’t a 
> show-stopper, since this will roll out in Swift 3.

Glad to hear breaking compatibility is ok in this case if it is required for 
consistency.

> 
> Here are the pros and cons as I see them with disallow-ing more-private 
> fields to be published through less-private memberwise inits:
> 
> Neutral: Either approach is fine for “CGRect” like types that are really just 
> public bags of public fields.
> Pro: Makes logical sense at first blush.  Memberwise inits publishing private 
> state would be odd/surprising.
> Pro: Safer default, in that you don’t accidentally publish stuff you don’t 
> want through a memberwise init.
> Con: This puts tension between access control for stored properties and 
> memberwise inits.  You have to choose between narrower access control or 
> getting the benefit of a memberwise init.  Another way to say it: this design 
> means that narrow access control leads to boilerplate.
> 
> I’m sure there are others as well.
> 
> Again, I don’t have a strong opinion, but I’d lean slightly towards 
> publishing all stored properties through the memberwise init.  If you don’t 
> have a strong opinion either, it would be fine to add a section pointing out 
> the tradeoffs, and we can all discuss it during the review period.  I suspect 
> some of the other core team folks will have an opinion on this as well.

I briefly addressed this in the alternatives considered section.  I’ll fill 
that out with additional details including the points you raise.

I feel pretty strongly that we should enforce the access control rules stated 
in the proposal.  In addition to the Pros you note:

1. I think it is usually the right thing to do.  If the caller can’t see a 
member it probably doesn’t make sense to allow them to initialize it.

2. If we expose more private-members by default then memberwise initialization 
is useless under the current proposal in many cases.  There would be no way to 
prevent synthesis of parameters for more-private members.  We have to choose 
between allowing callers to initialize our internal state or forgoing the 
benefit of memberwise initialization. 

3. If a proposal for `@nomemberwise` is put forward and adopted that would 
allow us to prevent synthesis of parameters for members as desired.  
Unfortunately `@nomemberwise` would need to be used much more heavily than it 
otherwise would (i.e. to prevent synthesis of memberwise parameters for 
more-private members).  It would be better if `@nomemberwise` was not necessary 
most of the time.

4. If callers must be able to provide memberwise arguments for more-private 
members directly it is still possible to allow that while taking advantage of 
memberwise initialization for same-or-less-private members.  You just need to 
declare a `memberwise init` with explicitly declared parameters for the 
more-private members and initialize them manually in the body.  Requiring the 
programmer to manually write any code that exposes more-private members is a 
arguably a very good thing.

I think #4 above addresses the con you mention pretty well and #2 above is a 
significant drawback to not enforcing the access control rule (#3 is also 
pretty significant IMO).

I’m sure this will be a point of discussion during review.  I’m prepared to 
defend the decision I made but will also keep my mind open to opposing 
arguments.

> 
> I sent you a PR (my first! :-) with some nit-picky details on the latest 
> writeup, to fix typos, clarify a few things, and reduce redundancy.  

Thanks!

> One point that I left:
> 
>> The *implicitly* synthesized initializer will be identical to an initializer 
>> declared *explicitly* as follows:
>> 
>> 1. For structs and root classes: `memberwise init(...) {}`
>> 2. For derived classes: `memberwise init(...) { super.init() }`
> 
> Note that these are both equivalent, since derived class initializers default 
> to super.init() at the bottom of their body today.  This is why you don’t 
> have to call super.init() when deriving from NSObject, for example.

I’ll add a note to make this clear.

> 
> 
>>> Thanks again for pushing this forward, you can also put me down as the 
>>> review manager if you’d like.
>>> 
>> 
>> You’re very welcome.  It’s a privilege to be able to contribute ideas, have 
>> them taken seriously and hopefully see them lead to progress in the 
>> language.  I’ve really enjoyed the process and discussions with the core 
>> team as well as the broader community.
>> 
>> It’s really incredible to see the Swift team embrace the community so openly 
>> and so graciously!
>> 
>> Merry Christmas!
> 
> You too Matthew, thanks again,
> 
> -Chris
> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to