<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 Jan 8, 2016, at 9:31 AM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Still, I can’t shake unease about the proposed solution. As I read the examples, they’re not quite self-explanatory: a lot of magic, but the result doesn’t feel quite magical. Without being able to see what the compiler synthesizes, it’s often not obvious what will happen. As I read the detailed rules, they all sound quite sensible, but taken together feel like they’ll be hard to keep track of, and will lead to a lot of frustrated experimenting with the compiler. Tricky questions lurk all over. For example, what happens when I have a 7-member struct, all 7 parameters use memberwise initialization, but then I want to add some custom logic for the initialization of member 3? I think I have to either reorder the params or abandon … altogether? I feel like those tricky questions should melt away once I grasp the underlying principle, but there isn’t one to grasp; it’s just a bunch of tricky cases.</div><div class=""><br class=""></div><div class="">On reflection, it comes down to this:<b class=""><span class="Apple-converted-space">&nbsp;</span>the feature to functionality ratio is too high.</b></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Would you propose removing the current implicit memberwise initializer for structs on the same grounds? &nbsp;This proposal effectively fleshes that feature out giving it more functionality. &nbsp;The only fundamental complexity it adds is the access control rules, which I feel are pretty important to enforce.</div></div></div></div></blockquote></div><br class=""><div class="">The struct memberwise behavior today is really simple and doesn’t expose a public API allowing for non-exhaustive behavior requirements and a much simpler design.</div><div class=""><br class=""></div><div class="">The struct rule is basically this:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">A member is added to the initializer when the following conditions are true:</div><div class="">&nbsp; &nbsp; 1. The member is not declared with let and an initialization value</div><div class="">&nbsp; &nbsp; 2. The member is not a computed property</div><div class=""><br class=""></div><div class="">Also, this generated initializer is only generated when no other init() has been defined.</div></blockquote><div class=""><br class=""></div><div class="">The really important observation though is that it keeps the generated initializer private, which means that there are no real API contracts to consider as it can only be used within your own code. It’s a nicety to have when simply building up some code to solve a problem.</div><div class=""><br class=""></div><div class="">The proposal essentially is doing two things:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; 1. Create a way to generate a public API contract based on a series of fairly complicated rules, potential annotations, and member orderings within the type</div><div class="">&nbsp; &nbsp; 2. Generate the pass through of assignment for the parameters of the init() and their backing values.</div><div class=""><br class=""></div><div class="">The vast amount complexity comes from trying to solve #1.</div><div class=""><br class=""></div><div class="">As for this:</div><div class=""><br class=""></div><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><blockquote type="cite" class="">(Aside, a small nitpick, but it really bugs me:&nbsp;initialization has O(M+N) complexity, not O(M×N) complexity. One doesn’t initialize every member with every parameter.)</blockquote></div></div></div></div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><div class=""><blockquote type="cite" class="">MxN is members x initializers.</blockquote></div></div></div><div class=""><br class=""></div><div class="">Paul, this has also bugged me too; I do not see how it is accurate. There aren’t N initializers, there is one initializer that must fully instantiate the type. Each type may have additional convenience initializers, but these are not required. Further, they cannot make use of the placeholder. There is a “futures” that talks about it, but that’s out of scope of the original proposal.&nbsp;</div><div class=""><br class=""></div><div class="">Your example hear illustrates the complexity (slightly modified from your proposal’s usage):</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&nbsp;</font><span style="font-family: Menlo;" class="">Foo {</span></div></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; let</span><span style="font-family: Menlo;" class="">&nbsp;bar:&nbsp;</span><span style="font-family: Menlo;" class="">String</span></div></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; let</span><span style="font-family: Menlo;" class="">&nbsp;bas:&nbsp;</span><span style="font-family: Menlo;" class="">Int</span></div></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; let</span><span style="font-family: Menlo;" class="">&nbsp;baz:&nbsp;</span><span style="font-family: Menlo;" class="">Double</span></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; init(self bar: String, self bas: Int, bax:&nbsp;Int</font><span style="font-family: Menlo;" class="">) {</span></div></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // self.bar = bar synthesized by the compiler</span></div></div><div class=""><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // self.bas = bas synthesized by the compiler</span></div></div></div><div class=""><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; self</span><span style="font-family: Menlo;" class="">.</span><span style="font-family: Menlo;" class="">baz&nbsp;</span><span style="font-family: Menlo;" class="">=</span><span style="font-family: Menlo;" class="">&nbsp;</span><span style="font-family: Menlo;" class="">Double</span><span style="font-family: Menlo;" class="">(bax)</span></div></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div></blockquote><div class="">The only thing I see your proposal removing is the re-typing of all of the members in the init signature that can be configured. And in fact, the current proposal doesn't support this. You have a futures section that looks a way to make this possible kinda like this:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">struct&nbsp;</font><span style="font-family: Menlo;" class="">Foo {</span></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; let</span><span style="font-family: Menlo;" class="">&nbsp;bar:&nbsp;</span><span style="font-family: Menlo;" class="">String</span></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; let</span><span style="font-family: Menlo;" class="">&nbsp;bas:&nbsp;</span><span style="font-family: Menlo;" class="">Int</span></div></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; let</span><span style="font-family: Menlo;" class="">&nbsp;baz:&nbsp;</span><span style="font-family: Menlo;" class="">Double</span></div></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; @nomemberwize(baz)</font></div><div class=""><font face="Menlo" class="">&nbsp; memberwise init(..., bax:&nbsp;Int</font><span style="font-family: Menlo;" class="">) {</span></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // self.bar = bar synthesized by the compiler</span></div></div><div class=""><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; // self.bas = bas synthesized by the compiler</span></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; self</span><span style="font-family: Menlo;" class="">.</span><span style="font-family: Menlo;" class="">baz&nbsp;</span><span style="font-family: Menlo;" class="">=</span><span style="font-family: Menlo;" class="">&nbsp;</span><span style="font-family: Menlo;" class="">Double</span><span style="font-family: Menlo;" class="">(bax)</span></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><div class=""><div class=""><br class=""></div></div><div class="">-David</div><div class=""><br class=""></div></body></html>