<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 26, 2015, at 11:31 PM, Chris Lattner &lt;<a href="mailto:clattner@apple.com" class="">clattner@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">On Dec 25, 2015, at 12:04 PM, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; wrote:<br class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">Discussion on a couple of topics continues inline below as well.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Great, comments below:</div></div></div></div></blockquote><div class=""><br class=""></div>Thanks for continuing the discussion. &nbsp;I have updated the proposal to reflect the core functionality and moved everything else to the future enhancements section. &nbsp;I think this draft is ready or nearly ready for a PR.</div><div class=""><br class=""></div><div class="">Here is a link to the current draft:&nbsp;<a href="https://github.com/anandabits/swift-evolution/edit/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md" class="">https://github.com/anandabits/swift-evolution/edit/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md</a></div><div class=""><br class=""></div><div class="">Here is a link to the commit diff:&nbsp;<a href="https://github.com/anandabits/swift-evolution/commit/f15360d2e201709640f9137d86a8b705a07b5466?short_path=f5ec377#diff-f5ec377f4782587684c5732547456b70" class="">https://github.com/anandabits/swift-evolution/commit/f15360d2e201709640f9137d86a8b705a07b5466?short_path=f5ec377#diff-f5ec377f4782587684c5732547456b70</a></div></div></div></blockquote><div class=""><br class=""></div><div class="">Thanks again for pushing this forward, this is looking great.</div></div></div></div></blockquote><div><br class=""></div>Sounds good. &nbsp;I just submitted a PR. &nbsp;I think it’s ready. &nbsp;Please let me know if you feel any further changes are necessary.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">It is also annoying that writing it as a static property would force you to write something like “X.a" instead of just “a”.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I agree with this. &nbsp;I can accept an argument that this provides enough value to avoid changing the language.</div><div class=""><br class=""></div><div class="">That said, I do think default values for let properties are higher value. &nbsp;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. &nbsp;But It would be great if we can find a way to support both.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">I understand your desire, but this really is something we’ll have to discuss carefully. &nbsp;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). &nbsp;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.</div></div></div></div></blockquote><div><br class=""></div><div>I know changing the existing behavior would require very careful thinking. &nbsp;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. &nbsp;What is the best way I can help to move this discussion forward in a productive manner? &nbsp;Would it be a good idea to start a new thread on the topic? &nbsp;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?</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">This I still have a concern with, in two ways:<br class=""><div class=""><br class=""></div><div class="">1) This still has tight coupling between the base and derived class. &nbsp;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. &nbsp;Specifically, across module boundaries, properties can change from stored to computed (or back) without breaking clients.</div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">2) You’re introducing another unnecessary feature "super.init(…)” which will have to be independently justified.&nbsp;</div><div class=""><br class=""></div></div></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">I will continue thinking about how this might be solved and also about other cases where such a forwarding feature might be useful. &nbsp;</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Sounds good. &nbsp;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 :-)</div></div></div></div></blockquote><div><br class=""></div><div>I agree with you on not holding back the base proposal. &nbsp;</div><div><br class=""></div><div>I really appreciate you noticing that this should really be orthogonal to the base proposal. &nbsp;I’ve already been giving this a lot of thought. &nbsp;It is very clear to me now that a much more general parameter / argument forwarding feature is the right approach. &nbsp;I am going to pursue a proposal for that as well.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Other comments:</div><div class=""><br class=""></div><div class="">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). &nbsp;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.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I’ll update that section to reflect these comments. &nbsp;</div><div class=""><br class=""></div><div class="">One question I have is what the implicit memberwise initializer should do in the case of private members. &nbsp;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. &nbsp;</div><div class=""><br class=""></div><div class="">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. &nbsp;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. &nbsp;How do you feel about this?</div></div></div></blockquote><div class=""><br class=""></div><div class="">I don’t have a strong opinion about this, and I can see reasonable arguments on either side. &nbsp;Breaking source compatibility in this case isn’t a show-stopper, since this will roll out in Swift 3.</div></div></div></div></blockquote><div><br class=""></div><div>Glad to hear breaking compatibility is ok in this case if it is required for consistency.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">Here are the pros and cons as I see them with disallow-ing more-private fields to be published through less-private memberwise inits:</div><div class=""><br class=""></div><div class="">Neutral: Either approach is fine for “CGRect” like types that are really just public bags of public fields.</div><div class="">Pro: Makes logical sense at first blush. &nbsp;Memberwise inits publishing private state would be odd/surprising.</div><div class="">Pro: Safer default, in that you don’t accidentally publish stuff you don’t want through a memberwise init.</div><div class="">Con: This puts tension between access control for stored properties and memberwise inits. &nbsp;You have to choose between narrower access control or getting the benefit of a memberwise init. &nbsp;Another way to say it: this design means that narrow access control leads to boilerplate.</div><div class=""><br class=""></div><div class="">I’m sure there are others as well.</div><div class=""><br class=""></div><div class="">Again, I don’t have a strong opinion, but I’d lean slightly towards publishing all stored properties through the memberwise init. &nbsp;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. &nbsp;I suspect some of the other core team folks will have an opinion on this as well.</div></div></div></div></blockquote><div><br class=""></div><div>I briefly addressed this in the alternatives considered section. &nbsp;I’ll fill that out with additional details including the points you raise.</div><div><br class=""></div><div>I feel pretty strongly that we should enforce the access control rules stated in the proposal. &nbsp;In addition to the Pros you note:</div><div><br class=""></div><div>1. I think it is usually the right thing to do. &nbsp;If the caller can’t see a member it probably doesn’t make sense to allow them to initialize it.</div><div><br class=""></div><div>2. If we expose more private-members by default then memberwise initialization is useless under the current proposal in many cases. &nbsp;There would be no way to prevent synthesis of parameters for more-private members. &nbsp;We have to choose between allowing callers to initialize our internal state or forgoing the benefit of memberwise initialization.&nbsp;</div><div><br class=""></div><div>3. If a proposal for `@nomemberwise` is put forward and adopted that would allow us to prevent synthesis of parameters for members as desired. &nbsp;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). &nbsp;It would be better if `@nomemberwise` was not necessary most of the time.</div><div><br class=""></div><div>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. &nbsp;You just need to declare a `memberwise init` with explicitly declared parameters for the more-private members and initialize them manually in the body. &nbsp;Requiring the programmer to manually write any code that exposes more-private members is a arguably a very good thing.</div><div><br class=""></div><div>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).</div><div><br class=""></div><div>I’m sure this will be a point of discussion during review. &nbsp;I’m prepared to defend the decision I made but will also keep my mind open to opposing arguments.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">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. &nbsp;</div></div></div></div></blockquote><div><br class=""></div><div>Thanks!</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">One point that I left:</div><div class=""><div class=""><br class=""></div><div class=""></div><blockquote type="cite" class=""><div class="">The *implicitly* synthesized initializer will be identical to an initializer declared *explicitly* as follows:</div><div class=""><br class=""></div><div class="">1. For structs and root classes: `memberwise init(...) {}`</div><div class="">2. For derived classes: `memberwise init(...) { super.init() }`</div></blockquote><div class=""><br class=""></div><div class="">Note that these are both equivalent, since derived class initializers default to super.init() at the bottom of their body today. &nbsp;This is why you don’t have to call super.init() when deriving from NSObject, for example.</div></div></div></div></div></blockquote><div><br class=""></div>I’ll add a note to make this clear.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div class=""><br class=""></div></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Thanks again for pushing this forward, you can also put me down as the review manager if you’d like.</div><div class=""></div><div class=""><br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">You’re very welcome. &nbsp;It’s a privilege to be able to contribute ideas, have them taken seriously and hopefully see them lead to progress in the language. &nbsp;I’ve really enjoyed the process and discussions with the core team as well as the broader community.</div><div class=""><br class=""></div><div class="">It’s really incredible to see the Swift team embrace the community so openly and so graciously!</div><div class=""><br class=""></div><div class="">Merry Christmas!</div></div></div></blockquote><br class=""></div><div class="">You too Matthew, thanks again,</div><div class=""><br class=""></div><div class="">-Chris</div><br class=""></div></div></blockquote></div><br class=""></body></html>