<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>+1 for disambiguating behavior vs. member access by a sigil. Using # is fine IMO.</div><div><br></div><div>-Thorsten&nbsp;</div><div><br>Am 18.01.2016 um 05:41 schrieb Curt Clifton via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;:<br><br></div><blockquote type="cite"><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>As long as we're bike shedding syntax, I'll add my two cents.&nbsp;</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">I'm not a fan of typed-based disambiguation of behavior vs. member references, as in foo.resettable.reset(). Behaviors are a very different thing than members. The proposed behavior declaration syntax makes this very clear. I think the reference syntax should do the same.</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">I also dislike the foo.[resettable].reset() alternative. This is primarily an aesthetic judgment—it looks like punctuation soup—but is also easy to read as the subscriptions foo[resettable] on a glance.</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">The double-dot approach is maybe somewhat better, but I worry that it's confusing with the range operators. (That may just be because of my experience in other languages that use '..'. Swift's '...' and '..&lt;' are probably sufficiently different.)</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">It seems to me that a sigil for both declaration and access would be clearer:<div id="AppleMailSignature"><br></div><div id="AppleMailSignature">// declaration</div><div id="AppleMailSignature">var #resettable foo: Int</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">// use</div><div id="AppleMailSignature">foo#resettable.reset()</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">// behavior composition</div><div id="AppleMailSignature">var #(lazy, resettable) bar: Int</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">This makes declaration and use correspond, keeps the syntax lightweight in the common case of a single behavior, and uses an ordered, tuple-like syntax for behavior composition.</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">Thanks for the updated proposal, Joe. I'm very excited to see where it goes.</div><br>Cheers,<div><br></div><div>Curt</div><div><br></div><div>Curt Clifton, PhD</div><div>Software Developer</div><div>The Omni Group</div><div><br></div></div><div><br>On Jan 14, 2016, at 10:43 AM, Wallacy via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div>I really liked this idea:<div><div><div style="color:rgb(34,34,34)"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(51,51,51)">x..<span class="" style="color:rgb(167,29,93)">resettablet</span>.reset()</span></pre></div></div>I can see that when typing the second dot, the autocomplete offering me all behaviors available. ;)<br><br>And thinking a little, may the `pipe` can be used to declaration :<br><br><div><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(51,51,51)"><span class="" style="color:rgb(167,29,93)">var</span> |<span class="" style="color:rgb(167,29,93)">lazy</span>| number <span class="" style="color:rgb(167,29,93)">=</span> </span><font color="#0000ff">1243</font></pre></div><div>The Square brackets is good, but feels like array.</div><div><br></div><div>And for multiple behaviors, we can use the "<b>&gt;</b>" to infer the "direction" of the "composability":<br></div><div><font color="#212121" face="Helvetica Neue, Helvetica, Arial, sans-serif"><br></font></div><div><pre style="color:rgb(34,34,34);overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style="color:rgb(51,51,51)"><span class="" style="color:rgb(167,29,93)">var</span> |<span class="" style="color:rgb(167,29,93)">lazy</span>&gt;</span><span style="color:rgb(167,29,93);font-size:13.6px;line-height:1.45">observed</span><font color="#333333" style="font-size:13.6px;line-height:1.45">| observedLazy </font><span class="" style="font-size:13.6px;line-height:1.45;color:rgb(167,29,93)">=</span><font color="#333333" style="font-size:13.6px;line-height:1.45"> expensiveExpression() {</font><br><font color="#333333">  </font><span class="" style="color:rgb(167,29,93)">didSet</span><font color="#333333"> { </font><span class="" style="color:rgb(0,134,179)">print</span><font color="#333333">(</font><span class="" style="color:rgb(24,54,145)"><span class="">"</span><span class="">\(</span><span class="" style="color:rgb(51,51,51)">oldValue</span><span class="">)</span> =&gt; <span class="">\(</span><span class="" style="color:rgb(51,51,51)">observedLazy</span><span class="">)</span><span class="">"</span></span><font color="#333333">) }
}</font></pre></div></div><div><font color="#333333"><br></font></div><br><div class="gmail_quote"><div dir="ltr">Em qui, 14 de jan de 2016 às 02:08, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; escreveu:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Jan 13, 2016, at 7:13 PM, Félix Cloutier &lt;<a href="mailto:felixcca@yahoo.ca" target="_blank">felixcca@yahoo.ca</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word"><div>I started by reading the examples and I was very confused. This suggests to me that if you've never seen a var behavior before, you are going to wonder what the hell is going on. :-)</div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>This is good feedback, thanks!</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div>Notable points of confusion:</div><div><br></div><div><ul><li>it's confusing to me that `self` is the containing type and the behavior name is the "behavior's self".</li></ul></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Others have noted this too. Would it be less confusing if one had to explicitly name the "container" as a member, e.g.:</div><div><br></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior synchronized {</div><div>&nbsp; container var parent: Synchronizable</div><div>&nbsp; base var value: Value</div><div><br></div><div>&nbsp; get {</div><div>&nbsp; &nbsp; return parent.withLock { value }</div><div>&nbsp; }</div><div>&nbsp; set {</div><div>&nbsp; &nbsp; parent.withLock { value = newValue }</div><div>&nbsp; }</div><div>}</div></div></blockquote><div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><ul><li>The `initializer` special field feels absolutely magic. Has anything else been considered, like an init param that has either a Value or an autoclosure returning one? (If we don't want to capture self, aren't we in for problems capturing self from accessors anyway?)</li></ul></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>An `init` parameter covers use cases where the initializer expression is used only during initialization, but doesn't let you use the initializer after initialization, which is necessary for `lazy`, `resettable`, and other use cases. Even with @autoclosure, it seems to me that, without `initializer`, we'd need to allocate per-property storage for the initializer expression to use it later, which is something I'd like to avoid.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><ul><li>I see (after reading it) that `var behavior foo&lt;Value&gt;: Value` means that foo "applies to"/"wraps" Value, but I find it confusing to use a syntax more typically associated with "extends" or "implements" or "is a".</li></ul></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Would it be less confusing if the type of the property were implicit? In discussion with Brent, I suggested a model where you say:</div><div><br></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior foo { ... }</div></div></blockquote><div><div><br></div><div>and if you want to constrain the types of properties that can instantiate the behavior, you use a where clause:</div><div><br></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior foo where Value: NSCopying { ... }</div><div><br></div></div></blockquote>which optimizes the common case (no constraint), and might be easier to read.<br><div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div>Questions:</div><div><br></div><div><ul><li>Can a behavior have generic parameters that can't be inferred? Could I write, say, [fooable&lt;Int&gt;]?</li></ul></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>No, the generic parameters are only used to generalize the property type.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><ul><li>What is the tradeoff between `eager` and `deferred`? Is it "only" that `deferred` side effects happen at the mercy of the behavior?</li><ul><li>If so, isn't it a problem that behaviors aren't intrinsically explicit about whether they defer initialization? I can see that causing very subtle bugs.</li></ul></ul></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>The tradeoff is that an 'eager' initialization can be used in `init`, but that means that an initializer expression can't refer to `self`, because `self` is not fully initialized. This is how initializer expressions always work today:</div><div><br></div><div>struct X {</div><div>&nbsp; var x = 0, y = 1</div><div>&nbsp; var z = x + y // Error</div><div>}</div><div><br></div><div>A deferred initialization can only be evaluated *after* init, but because of that, it can refer to `self`, which people would like to be able to do with `lazy` (but currently can't):</div><div><br></div><div>struct X {</div><div>&nbsp; var x = 0, y = 1</div><div>&nbsp; lazy var z = x + y // Theoretically OK</div></div></div><div style="word-wrap:break-word"><div><div>}</div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><br></div></div><div>Concerns:</div><div><br></div><div><ul><li>It looks like if you had a [resettable, observable] property, calling resettable.reset() would change the value from under `observable`'s feet.</li></ul></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>True. An unfortunate consequence of these things being user-defined is that there will always be "wrong" orderings of them. I'm not sure how much we can do about that.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><br></div><div>Comments:</div><div><br></div><div><ul><li>While it might be true that square brackets work better with other declarations that could eventually have behaviors, "var behavior" doesn't really lend itself to that kind of extensibility. Are we steering towards "func behavior", "class behavior", etc? Is it a problem if we are?</li></ul></div></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Possibly. Note that square brackets are necessary even only for `var`, because you can declare a destructuring binding `var (x, y) = tuple`.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><ul><li>I'd like to point out that the memoization example is a let variable with a behavior, which is explicitly forbidden by the current proposal.</li></ul></div></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Thanks, missed that.</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><br></div></div><div>Finally, I would like to throw the idea of "foo..resettable" to access foo's resettable behavior (or foo..reset() doing optionally-qualified lookup on foo's behavior methods).</div></div></div></blockquote><br></div></div><div style="word-wrap:break-word"><div></div><div>Not a bad suggestion.</div><div><br></div><div>Thanks again for the feedback!</div><div><br></div><div>-Joe</div><br>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=fuWmDRE6-2FDdvdUHeLHruUfdigJaxz7nh99l6HfkulY-2FhIk05hrMYxDaDcvvQr7bp-2BUSWvJckvPEzqKGuEu0WdpenaLwgOBBoLPeo7sNJmWpOJzNVgSJNXR6kCuk3tjqHDYALypG1iucgqu-2FoxMkYs3LmQKZFlHXD4qbqAYuTMHuNzXkAshgBkDKMvTX-2FUecfOsubxDqOgvrppgUEVoDQWrFUUnlbAS4PxUEaYrIQyTQ-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=87iKe3ucuzI0AomIMnNGId9Z44fJ2uc4Nj4u1iL4OH2ZTv-2BOch6FOgN8y0wuLR7Bf5gw7WvgiM2apSgo6rOJYGJvZEvwMYIQwQ0i0KssexDO70Y-2FZhrAjj91YwtDxA9nVIKvpNh0-2FTARMqamLE4kzYDo1Fe2oDPiHwqoXP-2FfMNoi-2BAcMBXpo2xCxwLSwbbOmLkurYzQOVR9fC3zCk-2BHfD-2BEq6hsxGIP3CpG4v3kGrkQ-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;">
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>