<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="">Le 13 janv. 2016 à 23:08:24, Joe Groff &lt;<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>&gt; a écrit :</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Notable points of confusion:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">var behavior synchronized {</div><div class="">&nbsp; container var parent: Synchronizable</div><div class="">&nbsp; base var value: Value</div><div class=""><br class=""></div><div class="">&nbsp; get {</div><div class="">&nbsp; &nbsp; return parent.withLock { value }</div><div class="">&nbsp; }</div><div class="">&nbsp; set {</div><div class="">&nbsp; &nbsp; parent.withLock { value = newValue }</div><div class="">&nbsp; }</div><div class="">}</div></div></blockquote></div></div></blockquote><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">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></blockquote><div><br class=""></div>I wish we didn't have immaterial members like `parent` (which would be an inout parameter to every method, it seems) and `initializer`, but I do prefer having an immaterial "container var parent" over a repurposed self. I can see the point with `initializer` (even though I'm not sure what that one would be).</div><div><br class=""></div><div>How are property behaviors "merged" into container types? Is there any chance that `initializer`, whether an autoclosure or a value, could be optimized away in most cases (screwed be debug builds)? That would be my favorite outcome.<br class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><ul class="MailOutline"><li class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">var behavior foo { ... }</div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">and if you want to constrain the types of properties that can instantiate the behavior, you use a where clause:</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">var behavior foo where Value: NSCopying { ... }</div><div class=""><br class=""></div></div></blockquote>which optimizes the common case (no constraint), and might be easier to read.<br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Questions:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">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 class=""><br class=""></div><div class="">No, the generic parameters are only used to generalize the property type.</div></div></div></div></blockquote><div><br class=""></div><div>Given this, I think that it makes sense to make the generics and remove the `: Value` (without the obvious downside that Value and Self are less discoverable).</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><ul class="MailOutline"><li class="">What is the tradeoff between `eager` and `deferred`? Is it "only" that `deferred` side effects happen at the mercy of the behavior?</li><ul class=""><li class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">struct X {</div><div class="">&nbsp; var x = 0, y = 1</div><div class="">&nbsp; var z = x + y // Error</div><div class="">}</div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">struct X {</div><div class="">&nbsp; var x = 0, y = 1</div><div class="">&nbsp; lazy var z = x + y // Theoretically OK</div><div class="">}</div></div></div></div></blockquote><div><br class=""></div><div>Got it. Still, can it be a problem that it might not be obvious whether a behavior defers initialization or not, in terms of side effects?</div><div><br class=""></div><div>Also, some behaviors (like resettable) use `initializer` multiple times. Are the side effects evaluated each time? That seems like a bad idea to me, but it does mean that `initializer`'s value would need to be stored otherwise.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Concerns:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">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 class=""><br class=""></div><div class="">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></blockquote><div><br class=""></div><div>In this case, it's problematic that resettable simply can't be ordered after observable because it has a base property.</div><div><br class=""></div><div>Would it make sense to have a warning if a behavior down the chain has mutating functions? (Either at the declaration or at the mutating call site)</div><div><br class=""></div><div>Speaking of which, `lazy`'s `get` accessor isn't marked as mutating in the proposal. Is it on purpose?</div><div><br class=""></div><div>Thanks for your work on this.</div><div><br class=""></div><div>Félix</div><div><br class=""></div></div></body></html>