<div dir="ltr">@Joe could you elaborate on the access pattern for these properties? Are you getting back a boxed object every time or is there some sort of magic going on so the caller thinks its getting the value inside the box but still has some way to access methods on the box (say reset for the lazy property)</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Dec 21, 2015 at 1:04 PM Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<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">I really like the direction this is heading Joe!  I agree it feels a lot nicer.  It seems like the right long-term solution to me.<div><br></div><div>Making behaviors an explicit construct in the language may lead to possibilities in the future that we cannot today which would not exist with the ad-hoc approach. </div></div><div style="word-wrap:break-word"><div><div><br><div><blockquote type="cite"><div>On Dec 21, 2015, at 11:23 AM, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word">I played around a bit with the idea of a special behavior declaration. I think it feels a lot nicer, though it also feels like a much bigger language change if we go this route. Inside the declaration, you need to specify:<div>- what accessors the behavior supports, to be implemented by properties using the behavior,</div><div>- if the behavior controls storage, what that storage is, and what initialization logic it requires,</div><div>- if the behavior requires an initializer, and whether that initializer is used eagerly at property initialization or deferred to later, and</div><div>- what operations the behavior offers, if any.</div><div><br></div><div>Here&#39;s a quick sketch of how a behavior declaration could look. As a strawman, I&#39;ll use &#39;var behavior&#39; as the introducer for a property behavior (leaving the door open to &#39;func behavior&#39;, &#39;struct behavior&#39;, etc. in the possible future). If you were going to reinvent computed properties from whole cloth, that might look like this:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior computed&lt;T&gt; {</div></div><div>  // A computed property requires a `get` and `set` accessor.</div><div><div>  accessor get() -&gt; T</div></div><div><div>  accessor set(newValue: T)</div></div><div><div><br></div></div><div>  // Accessors for the property</div><div><div>  get { return get() }</div></div><div><div>  set { set(newValue) }</div></div><div><div>}</div></div></blockquote><div><div><br></div></div><div>lazy might look something like this:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior lazy&lt;T&gt; {</div></div><div>  // lazy requires an initializer expression, but it isn&#39;t</div><div>  // used until after object initialization.</div><div><div>  deferred initializer: T</div></div><div><div><br></div></div><div>  // The optional storage for the property.</div><div><div>  var value: T?</div></div><div><div><br></div></div><div>  // Initialize the storage to nil.</div><div><div>  init() {</div></div><div><div>    value = nil</div></div><div><div>  }</div></div><div><div><br></div></div><div>  // Accessors for the property.</div><div><div>  mutating get {</div></div><div><div>    if let value = value {</div></div><div><div>      return value</div></div><div><div>    }</div></div><div>    // `initializer` is implicitly bound to the initializer expr as a</div><div>    // `@noescape () -&gt; T` within the behavior&#39;s members.</div><div><div>    let initialValue = initializer()</div></div><div><div>    value = initialValue</div></div><div><div>    return initialValue</div></div><div><div>  }</div></div><div><div><br></div></div><div><div>  set {</div></div><div><div>    value = newValue</div></div><div><div>  }</div></div><div><div><br></div></div><div>  // clear() operation for the behavior.</div><div><div>  mutating func clear() {</div></div><div><div>    value = nil</div></div><div><div>  }</div></div><div><div>}</div></div></blockquote><div><div><br></div></div><div>Some behaviors like `lazy` and `resettable` want to take control of the storage to manage their semantics, but many behaviors are adapters independent of how the underlying behavior behaves. These kinds of behavior are easy to compose with other behaviors and to override base class properties with. You could use inheritance-like syntax to indicate a &quot;wrapping&quot; behavior like this, and commandeer `super` to refer to the underlying property. For instance, `synchronized`:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior synchronized&lt;T&gt;: T {</div></div><div><div>  get {</div></div><div><div>    return sync { return super }</div></div><div><div>  }</div></div><div><div>  set {</div></div><div><div>    return sync { return super }</div></div><div><div>  }</div></div><div><div>}</div></div></blockquote><div><div><br></div></div><div>or `observing` didSet/willSet:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>var behavior observing&lt;T&gt;: T {</div></div><div><div>  accessor willSet(oldValue: T, newValue: T) { }</div></div><div><div>  accessor didSet(oldValue: T, newValue: T) { }</div></div><div><div><br></div></div><div><div>  get { return super }</div></div><div><div>  set {</div></div><div>    let oldValue = super</div><div><div>    willSet(oldValue, newValue)</div></div><div><div>    super = newValue</div></div><div><div>    didSet(oldValue, newValue)</div></div><div><div>  }</div></div><div><div>}</div></div></blockquote><div><br></div><div>If you want to refer back to the containing `self`, we could support that too, and by treating behavior functions specially we should be able to maintain coherent semantics for backreferencing value types as well. Implementing `synchronized` with a per-object lock could look like this:</div><div><br></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>var behavior synchronizedByObject&lt;T&gt;: T where Self: Synchronizable {</div><div>  get {</div><div>    return self.withLock { return super }</div><div>  }</div><div>  set {</div><div>    return self.withLock { return super }</div><div>  }</div><div>}</div><div><br></div></blockquote>(though the juxtaposed meanings of `super` and `self` here are weird together…we&#39;d probably want a better implicit binding name for the underlying property.)<div></div></div><div><br></div><div>-Joe</div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=eLFMrKDT8iBxZ-2Fbnk-2BZqvSchNN-2FvYXdceA0T7VxwkAdB7f5kPel3wVVhZxLSddb-2FldjgOHakJarBMOyzAELLOuvB0h52c6hlV5Opv9Nqc9Z8EMVa3VYcHGKNDjHlrfGCTKQRmaVWUwLtvY9dMKtOJZnO9bG3Sym9sIOpYWxqPxlOADxujvnHBFqCiH3f0aqk39OZHV29ScuGERA4H56U3uY0oA55ORIisRewzOkvv-2Fk-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" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br></div></div></div><div style="word-wrap:break-word"><div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=RVJ3oK8DhV2nk8GArr3gdPiHJ-2FGbeDKSQCjTA2mYAuInDp9uvnJQX0V8dj0Jx8lbT-2FsEUpX0hS9tvCJvls2ZIFuO-2BJW5NHDwi4EQ-2FlQVBQp8VYJKA9YwLYJPcOoctVotcvsm7cJuTMMGA0KbqboIOSth3dSurEJOrbPufo8C54x-2F4b74e71L8XDqgjEllxwg0YV5rAi7lPYFLpFahMMmBg-3D-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>