<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="">I really like the idea and it’s something that’s extremely annoying to deal with today in Swift. My biggest concern is that the proposal, in its entirety, seems to really complicate the initialization rules.<div class=""><br class=""></div><div class="">Also, I don’t think it generates good API signatures. Take this example:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">struct S {</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let s: String</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let i: Int</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// user declares:</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>memberwise init() {}</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// compiler synthesizes:</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>init(s: String, i: Int) {</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>self.s = s</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>self.i = i</font></div></div><div class=""><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><div class=""><div class=""><div class=""><br class=""></div><div class="">That is not a very descriptive API. It’s also not necessarily the case that your internal names are what you want exposed.</div><div class=""><br class=""></div><div class="">I would actually prefer the rule to simply be this: when an init() is modified by <i class="">memberwise</i>, the labelled parameters will be set. This lookup will try both the argument name and the parameter name, in that order, for reasons that become more clear with convenience inits described later.</div><div class=""><br class=""></div><div class="">So you would have this:</div><div class=""><br class=""></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><font face="Menlo" class="">memberwise init(name s: String, value i: Int) {</font></div></div></div><div class=""><font face="Menlo" class=""> // autogenerated: self.s = s; self.i = i</font></div><div class=""><span style="font-family: Menlo;" class="">}</span></div></blockquote><div class=""><div class=""><div class=""><br class=""></div><div class="">This provides you all of the freedom that you may need:</div><div class=""><ol class="MailOutline"><li class="">Order of the APIs is explicitly controlled</li><li class="">API names of the members are not exposed if not desired, especially helpful for non-public members</li><li class="">Default values are handled naturally</li></ol><div class=""><br class=""></div></div><div class="">Optionally, you could keep the default simply with this:</div><div class=""><br class=""></div></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><div class=""><font face="Menlo" class="">memberwise init {}</font></div></div></div></div></blockquote><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div><div class="">This would use the property names as the argument labels.</div><div class=""><br class=""></div><div class="">Another example:</div><div class=""><br class=""></div><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">memberwise init(name s: String, value i: Int = 12) {</font></div><div class=""><font face="Menlo" class=""> // autogenerated: self.s = s; self.i = i</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><div class=""></div></div></div><div class=""><br class=""></div><div class="">And the usage is much nicer:</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class=""><font face="Menlo" class="">let s = S(name: "Happy")</font></div></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">Here’s a subclassing example:</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">class Animal {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> let type: String</font></div></div><div class=""><div class=""><font face="Menlo" class=""> let numberOfLegs: Int</font></div></div><div class=""><div class=""><font face="Menlo" class=""> </font></div></div><div class=""><div class=""><font face="Menlo" class=""> memberwise init(type: String, numberOfLegs: Int) {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ self.type = type</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ self.numberOfLegs = numberOfLegs</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">class Dog: Animal {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> let name: String</font></div></div><div class=""><div class=""><font face="Menlo" class=""> </font></div></div><div class=""><div class=""><font face="Menlo" class=""> memberwise private init(type: String = "dog", numberOfLegs: Int = 4, n name: String) {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ self.name = name</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ super.init(type: type, numberOfLegs: numberOfLegs);</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class=""> </font></div></div><div class=""><div class=""><font face="Menlo" class=""> memberwise convenience init(name: String) {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ self.init(type: "dog", numberOfLegs: 4, n: name)</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">let d = Dog(name: "Fido")</font></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">The biggest thing about convenience inits is that the generation of the init needs to pull the defaults from the designated init. Also, for super.init(), it’s a straight label/name lookup for the <i class="">designated</i> init() only. Anything more fancy must be written by the user.</div><div class=""><br class=""></div><div class="">You also disallow private init, but that doesn’t need to happen with explicit members. That’s the beauty of giving the public API a real contract with names.</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">struct S {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> let s: String</font></div></div><div class=""><div class=""><font face="Menlo" class=""> private let i: Int</font></div></div><div class=""><div class=""><font face="Menlo" class=""> </font></div></div><div class=""><div class=""><font face="Menlo" class=""> memberwise init(name s: String, value i: Int = 12) {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ self.s = s</font></div></div><div class=""><div class=""><font face="Menlo" class=""> /* generated */ self.i = i</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">Also, partial initialization <i class="">could</i> be possible, much like you proposed originally:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">struct S {</font></div><div class=""><font face="Menlo" class=""> let s: String</font></div><div class=""><font face="Menlo" class=""> private let i: Int</font></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> memberwise init(name s: String) {</font></div><div class=""><font face="Menlo" class=""> /* generated */ self.s = s</font></div><div class=""><font face="Menlo" class=""> self.i = s.utf8.count</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><br class=""></div><div class="">My concern is that this starts to be more complicated and magical. I’d actually cut this from the proposal.</div><div class=""><br class=""></div><div class="">The last change I would make is that if any property has an assignment in the declaration, it cannot be memberwise initialized.</div><div class=""><br class=""></div><div class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">struct S {</font></div><div class=""><font face="Menlo" class=""> let s: String</font></div><div class=""><font face="Menlo" class=""> let i: Int = 10</font></div><div class=""><font face="Menlo" class=""> </font></div><div class=""><font face="Menlo" class=""> memberwise init(name s: String) {</font></div><div class=""><font face="Menlo" class=""> /* generated */ self.s = s</font></div><div class=""><span style="font-family: Menlo;" class=""> }</span></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""></div></div><div class=""><br class=""></div><div class="">In the above, <i class="">i </i>will always be 10.</div><div class=""><br class=""></div><div class="">-David</div><div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class="">On Dec 21, 2015, at 11:32 AM, Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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="">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.<div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><a href="https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md" class="">https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md</a></div></div></div></blockquote></div><br class=""></div></div></body></html>