<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 13, 2016, at 8:44 PM, Félix Cloutier <<a href="mailto:felixcca@yahoo.ca" class="">felixcca@yahoo.ca</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" 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="">Le 13 janv. 2016 à 23:08:24, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> 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=""> container var parent: Synchronizable</div><div class=""> base var value: Value</div><div class=""><br class=""></div><div class=""> get {</div><div class=""> return parent.withLock { value }</div><div class=""> }</div><div class=""> set {</div><div class=""> parent.withLock { value = newValue }</div><div class=""> }</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 class=""><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></div></blockquote><div><br class=""></div><div>One benefit of making the container binding explicit is that we can avoid referencing the container `inout` in behavior implementations if it isn't used (and we're willing to say that a behavior can't resiliently adopt a container requirement if it wasn't originally written with one).</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=""></div><div class="">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=""></div></div></div></blockquote><div><br class=""></div><div>The initializer expression and accessors should manifest themselves as methods on the containing type. There shouldn't be any implicit per-instance storage overhead to using behaviors, and the abstraction should be optimizable by inlining and generic specialization in optimized builds.</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=""><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<Value>: 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<Int>]?</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 class=""><br class=""></div><div class="">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=""> var x = 0, y = 1</div><div class=""> 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=""> var x = 0, y = 1</div><div class=""> lazy var z = x + y // Theoretically OK</div><div class="">}</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">In this case, it's problematic that resettable simply can't be ordered after observable because it has a base property.</div></div></div></div></blockquote><div><br class=""></div><div>It occurs to me that a bound `initializer` is in a sense a lot like a sugared accessor. Both `lazy` and `resettable` could be designed in terms of accessor requirements, at the cost of some sugar, and some redundancy in the case of `resettable`:</div><div><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div>var behavior lazy {</div></div><div><div> var value: Value?</div></div><div><div> accessor initialValue() -> Value</div></div><div><div><br class=""></div></div><div><div> mutating get {</div></div><div><div> if let value = value { return value }</div></div><div><div> let val = initialValue()</div></div><div><div> value = val</div></div><div><div> return val</div></div><div><div> }</div></div><div><div>}</div></div><div><div><br class=""></div></div><div><div>var [lazy] x: Int {</div></div><div><div> initialValue { return 679 }</div></div><div><div>}</div></div><div><div><br class=""></div></div><div><div>var behavior resettable {</div></div><div><div> base var value: Value</div></div><div><div> accessor resetValue() -> Value</div></div><div><div><br class=""></div></div><div><div> mutating func reset() {</div></div><div><div> value = resetValue</div></div><div><div> }</div></div><div><div>}</div></div><div><div><br class=""></div></div><div><div>var [resettable] y: Int = 1738 {</div></div><div><div> resetValue { return 1738 }</div></div><div><div>}</div></div></blockquote><div><br class=""></div><div>If we could live with that, we could avoid the complexity of the deferred/eager initializer, and `resettable` could also be made composable by a base property.</div><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=""><div class=""><br class=""></div><div class="">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></div></div></blockquote><div><br class=""></div><div>Not sure what you mean, exactly. Seems like that would warn on a lot of legitimate use cases.</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=""><div class="">Speaking of which, `lazy`'s `get` accessor isn't marked as mutating in the proposal. Is it on purpose?</div></div></div></div></blockquote><div><br class=""></div><div>Another oversight; thanks!</div></div><br class=""><div class="">-Joe</div></body></html>