<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=""><div><blockquote type="cite" class=""><div class="">On Jan 8, 2016, at 11:31 AM, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: HelveticaNeue; font-size: 13px; 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=""><blockquote type="cite" class=""><div class="">On Jan 8, 2016, at 11:03 AM, Paul Cantrell 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;">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></blockquote></div></div></blockquote><blockquote type="cite" class=""><div style="font-family: HelveticaNeue; font-size: 13px; 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=""><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=""><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 class=""><br class=""></div><div class="">Would you propose removing the current implicit memberwise initializer for structs on the same grounds?</div></div></blockquote><div><br class=""></div><div>No, it’s a much smaller feature surface. I would proposed promoting it from a simple, situational feature to something very generic — much like what Joe Groff is doing with “lazy.”</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: HelveticaNeue; font-size: 13px; 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=""><div class="">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></blockquote><div><br class=""></div><div>I tend to agree with others who think the additional complexity in this proposal is substantial. Perhaps it would come to seem simple if we all lived with it, though that’s not my gut reaction. It’s a lot of hidden rules.</div><div><br class=""></div><blockquote type="cite" class=""><div style="font-family: HelveticaNeue; font-size: 13px; 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=""><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="">It feels to me like this functionality should come from a feature set that is more general, more arbitrarily composable, and pays greater dividends in a wider variety of situations. As a simple example, what if I want to write an updateFrom(other: Self) method that does a mass copy of all properties? Why doesn’t this proposal help with that, too? Because the … placeholder and the synthesized copying are tightly coupled (1) to each other and (2) to initialization.</div><div class=""><br class=""></div><div class="">I’m not sure what the better answer is, but it’s out there. I didn’t follow the whole discussion, but I did notice Joe Groff’s proposal for a Members tuple; that seems to me to be getting much warmer. I’d much prefer something along those lines, even if it were slightly more verbose.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I think the direction suggested by Joe (and Dave) is interesting. &nbsp;But they haven’t explained how it would handle some important use cases this proposal addresses (default parameter values, subset of members without using a struct, etc). &nbsp;If we are going to reject this proposal in hope of a more general solution I would at least like to see a path forward that might be able to address these use cases.</div></div></blockquote><div><br class=""></div><div>Agreed — I think this proposal has tremendous value at the <i class="">very</i> least as an in-depth exploration of all the cases to consider in searching for a more general solution.</div><br class=""><blockquote type="cite" class=""><div style="font-family: HelveticaNeue; font-size: 13px; 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=""><div class="">More importantly, the general features on their own would not address the problems addressed by this proposal. &nbsp;There would still need to be initializer-specific magic. &nbsp;Joe hinted at what that might be but has not fleshed out all the details yet. &nbsp;Maybe it would be a simpler model but we would need to see more specific details.</div><div class=""><br class=""></div><div class="">I don’t believe a fully generalized solution is possible. &nbsp;There are a lot of initialization-specific constraints that must be met (definitive initialization, single initialization of `let` properties, etc).</div></div></blockquote><div><br class=""></div><div>As I said in the original review, I’d be willing to sacrifice some concision in service of making the solution more general.</div><div><br class=""></div><div>For example, the proposal goes to lengths to (1) automatically select a subset of members for memberwise initialization and (2) automatically insert the initialization code. I’d be willing to sacrifice both those implicit behaviors for some more generically composable mechanisms that let me turn a (sub)set of members into a tuple type, add it to arg lists, and mass assign it.</div><div><br class=""></div><div>Here’s a sketch of that — not a proposal, total BS syntax, totally hypothetical:</div><div><br class=""></div><div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;<span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">struct</span> S {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">let</span> s0, s1, s2: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">private</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">let</span> i: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">Int</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">init</span>(anInt: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">Int</span>, anotherInt: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">Int</span>, otherArgs: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">Members.</span>except(<span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">i</span>)) {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; members =&nbsp;otherArgs&nbsp;&nbsp;<span style="color: rgb(102, 139, 73); font-size: 10.5px;" class="">// assigned members inferred from tuple item names</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i = anInt &gt; anotherInt ? anInt : anotherInt</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div class=""><br class=""></div></div><div>I’d be happy — happier! — with a solution like that, despite the modest additional keystrokes, because (1)&nbsp;<span style="font-family: Menlo; font-size: 11px;" class="">members</span>&nbsp;and&nbsp;<span style="color: rgb(88, 126, 168); font-family: Menlo; font-size: 11px;" class="">Members</span>&nbsp;would presumably have a more predictable behavior that’s easier to remember and to understand by reading, and (2) they’d be usable in other contexts:</div><div><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;<span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">mutating</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">func</span> updateFrom(other: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">S</span>) {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">self</span>.members = other<span style="font-size: 10.5px;" class="">.except(i)</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; i = anInt &gt; anotherInt ? anInt : anotherInt</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div class=""><br class=""></div><div class="">…or heck, even this:</div><div class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;<span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">mutating</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">func</span> updateTwoStrings(s0: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>, s1: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>) {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; members = arguments</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">mutating</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">func</span> updateTwoStrings(s0: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>, s1: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>, message: <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>) {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">print</span>(message)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; members = arguments.except(message)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div class=""><br class=""></div><div class="">OK, I concede I'm now brainstorming quite a feature list here:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class=""><span style="font-family: Menlo; font-size: 11px;" class="">members</span>&nbsp;property that turns all (stored?) properties into a tuple,</li><li class=""><span style="color: rgb(88, 126, 168); font-family: Menlo; font-size: 11px;" class="">Members</span>&nbsp;property that returns the type of the above,</li><li class=""><span style="font-family: Menlo; font-size: 11px;" class="">select<span style="font-family: 'Helvetica Neue'; font-size: 13px;" class="">&nbsp;/&nbsp;</span>except</span>&nbsp;operations on any tuple that create a new tuple by filtering keys,</li><li class="">assignment of a tuple to&nbsp;<span style="font-family: Menlo; font-size: 11px;" class="">members</span>&nbsp;that matches by tuple key (and the tuple can contain a subset of all properties),</li><li class=""><span style="font-family: Menlo; font-size: 11px;" class=""><span style="font-family: 'Helvetica Neue'; font-size: 13px;" class="">some way of variadically expanding a tuple type in an arg list, and</span></span></li><li class=""><span style="font-family: Menlo; font-size: 11px;" class="">arguments</span>&nbsp;implicit variable that gives all func args as a tuple. (That last one’s not necessary to replace this proposal; just threw it in there because I’m brainstorming.)</li></ul></div><div class=""><br class=""></div><div class="">That’s a lot! But all these feature are more independent, flexible, and transparent than the ones in the proposal. They (1) need not all be understood all at once, (2) have less implicit behavior and rules about corner cases, (3) thus have a simpler mental model and are easier to understand just by reading, and (4) provide more capabilities in a broader range of contexts.</div><div class=""><br class=""></div><div class="">Again, it’s only a sketch. Just making stuff up here! The obvious question is “how <i class="">exactly</i> would it all work,” and I don’t know either — but I feel like it could, and I’d really like to pursue this sort of direction before going with the more narrow proposal at hand.</div><div class=""><br class=""></div><div class="">That said, I originally wrote:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="font-family: HelveticaNeue;"><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">I think it should be deferred in search of a more generic solution, perhaps to be resurrected if the search for generality fails.</div></div></blockquote></div></blockquote></div><div class=""><br class=""></div><div class="">I said “deferred” instead of “rejected” because my objection is that there <i class="">may</i>&nbsp;be a better solution — but that’s only a gut feeling, and if we really truly establish that there isn’t, then I’d give this proposal another look.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div style="font-family: HelveticaNeue; font-size: 13px; 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=""><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="">(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.)</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">MxN is members x initializers.</div></div></blockquote></div><br class=""><div class="">Yes, as others pointed out, my careless misreading! Makes much more sense now. Sorry for that.</div><div class=""><br class=""></div><div class="">Cheers,</div><div class=""><br class=""></div><div class="">Paul</div><div class=""><br class=""></div></body></html>