<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 19, 2016, at 4:28 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; 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 19, 2016, at 3:10 PM, Joe Groff &lt;<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>&gt; wrote:</div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class="">On Jan 19, 2016, at 2:46 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</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;"><div class=""><blockquote type="cite" class=""><div class="">On Jan 13, 2016, at 2:07 PM, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><div class="">Thanks everyone for the first round of feedback on my behaviors proposal. I've revised it with the following changes:<br class=""><br class="">- Instead of relying on mapping behaviors to function or type member lookup, I've introduced a new purpose-built 'var behavior' declaration, which declares the accessor and initializer requirements and provides the storage and behavior methods of the property. I think this gives a clearer design for authoring behaviors, and allows for a more efficient and flexible implementation model.<br class="">- I've backed off from trying to include 'let' behaviors. As many of you noted, it's better to tackle immutable computed properties more holistically than to try to backdoor them in.<br class="">- I suggest changing the declaration syntax to use a behavior to square brackets—'var [behavior] foo'—which avoids ambiguity with destructuring 'var' bindings, and also works with future candidates for behavior decoration, particularly `subscript`.<br class=""></div></div></blockquote><div class=""><br class=""></div></div>Syntax comments:<div class=""><br class=""></div><div class="">I still think these feel attribute-like to me, but if we’re not just going to use @lazy — and I agree that that does have some problems —I’m fine with [lazy].<br class=""></div></div></div></blockquote><div class=""><br class=""></div><div class="">I'm OK with using attribute syntax alongside the declaration approach.</div><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=""><br class=""></div><div class="">"var behavior" is really weird to me, and the &lt;T&gt; doesn’t seem to fit and is pretty redundant in the common case. &nbsp;How about this:</div></div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">&nbsp;&nbsp;"behavior" var-or-let "[" identifier-list "]" (identifier |&nbsp;</font><span class="" style="font-family: Menlo;">"</span><font face="Menlo" class="">_</font><span class="" style="font-family: Menlo;">")</span><span class="" style="font-family: Menlo;">&nbsp;":" identifier (</span><span class="" style="font-family: Menlo;">"="</span><span class="" style="font-family: Menlo;">&nbsp;</span><span class="" style="font-family: Menlo;">identifier)?&nbsp;</span><span class="" style="font-family: Menlo;">("where" generic-requirement-list)?</span></div><div class=""><br class=""></div><div class="">So, for example,</div><div class=""><font face="Menlo" class="">&nbsp; behavior var [lazy] _ : T where T : IntegerLiteralConvertible { … }</font></div><div class=""><br class=""></div><div class="">This is definitely taking the idea of “this is basically a macro” and running with it. &nbsp;Think of the stuff between “behavior” and the optional “where” as being a pattern for the declaration. &nbsp;So this pattern would match:</div><div class=""><font face="Menlo" class="">&nbsp; var [lazy] x: Int</font></div><div class="">but not:</div><div class=""><font face="Menlo" class="">&nbsp; let [lazy] x: Int</font></div><div class="">or:</div><div class=""><font face="Menlo" class="">&nbsp; var [lazy] x : Int = foo()</font></div></div></div></blockquote><div class=""><br class=""></div><div class="">Good idea, I like this approach. However:</div><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="">The behavior list has to match exactly (or maybe as sets?).</div></div></div></blockquote><div class=""><br class=""></div><div class="">Are you saying that there would be no ad-hoc composition of behaviors? This seems to imply that you'd need to implement every valid combination of behaviors by hand. That's a defensible position, given that it's easy to compose behaviors like "synchronized" in the wrong order, but significantly stifles behaviors like didSet/willSet that are more likely to be order-agnostic.</div></div></div></div></blockquote><div class=""><br class=""></div>My first instinct is to say that ad-hoc composition is too treacherous to include in the first model, yeah.</div><div style="font-family: Helvetica; font-size: 12px; 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=""></div><div style="font-family: Helvetica; font-size: 12px; 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="">I like the idea of having a model that works for literally everything that’s not pure-computed or pure-stored, but it seems tolerable to continue to build in things like willSet / didSet if it significantly simplifies the problem. &nbsp;willSet / didSet have some pretty custom behavior and dependencies on the container. &nbsp;OTOH, maybe that kind of thing is a core requirement for some of the stuff we’re thinking of doing.</div></div></blockquote><div><br class=""></div><div>I think you can define a reasonable facsimile of willSet/didSet under my proposal, but I'm willing to believe there are edge cases I'm missing. What sort of custom behavior do you have in mind?</div><div><br class=""></div><div>-Joe</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; 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=""><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="">The property name, if bound, expands to a string literal within the behavior.</div><div class=""><br class=""></div><div class="">The type name is always a generic parameter. &nbsp;This interferes with the ability to make a pattern that only matches a concrete type, but I think that’s okay.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Seems reasonable, since unconstrained behaviors are likely to be the 95% case. Being able to match concrete types is something we ought to be able solve uniformly with the same limitation on constrained extensions.</div></div></div></div></blockquote><div class=""><br class=""></div>Yeah.</div><div style="font-family: Helvetica; font-size: 12px; 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=""><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="">The initializer name, if bound, expands to the original expression within the behavior. &nbsp;Maybe it should be coerced to type T first? &nbsp;Not sure.</div></div></div></blockquote><br class=""></div><div class="">Yeah, JoeP brought up a good question about how 'var' type inference should work with initializer expressions. There are two possible models I can see:</div><div class=""><br class=""></div><div class="">- We infer the type of the initializer independent of any applied behaviors, and raise an error if the behavior can't be instantiated at the given type.</div><div class="">- We add generic constraints from the behavior declaration(s) to the contextual type of the initializer.</div><div class=""><br class=""></div><div class="">In support of the latter approach, 'weak' properties currently factor their Optional constraint into type inference ('weak var foo = Foo()' gives you a property of type Foo?), and 'weak' has been raised as a candidate for eventual behavior-ization. The downside, of course, is that with arbitrary user-defined behaviors with arbitrary generic constraints, there's yet another source of potential surprise if the type context of behaviors changes the type-checking of an expression.</div></div></div></blockquote><div class=""><br class=""></div>Yeah, especially because the initializer could be used in multiple places in the behavior. &nbsp;Coercing the initializer seems a lot less surprising.</div><div style="font-family: Helvetica; font-size: 12px; 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=""></div><div style="font-family: Helvetica; font-size: 12px; 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="">John.</div></div></blockquote></div><br class=""></body></html>