<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,&#39;Liberation Mono&#39;,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,&#39;Liberation Mono&#39;,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 &quot;<b>&gt;</b>&quot; to infer the &quot;direction&quot; of the &quot;composability&quot;:<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,&#39;Liberation Mono&#39;,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="">&quot;</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="">&quot;</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&#39;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&#39;s confusing to me that `self` is the containing type and the behavior name is the &quot;behavior&#39;s self&quot;.</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 &quot;container&quot; 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>  container var parent: Synchronizable</div><div>  base var value: Value</div><div><br></div><div>  get {</div><div>    return parent.withLock { value }</div><div>  }</div><div>  set {</div><div>    parent.withLock { value = newValue }</div><div>  }</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&#39;t want to capture self, aren&#39;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&#39;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&#39;d need to allocate per-property storage for the initializer expression to use it later, which is something I&#39;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 &quot;applies to&quot;/&quot;wraps&quot; Value, but I find it confusing to use a syntax more typically associated with &quot;extends&quot; or &quot;implements&quot; or &quot;is a&quot;.</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&#39;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 &quot;only&quot; that `deferred` side effects happen at the mercy of the behavior?</li><ul><li>If so, isn&#39;t it a problem that behaviors aren&#39;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 &#39;eager&#39; initialization can be used in `init`, but that means that an initializer expression can&#39;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>  var x = 0, y = 1</div><div>  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&#39;t):</div><div><br></div><div>struct X {</div><div>  var x = 0, y = 1</div><div>  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`&#39;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 &quot;wrong&quot; orderings of them. I&#39;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, &quot;var behavior&quot; doesn&#39;t really lend itself to that kind of extensibility. Are we steering towards &quot;func behavior&quot;, &quot;class behavior&quot;, 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&#39;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 &quot;foo..resettable&quot; to access foo&#39;s resettable behavior (or foo..reset() doing optionally-qualified lookup on foo&#39;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>