[swift-evolution] [Proposal] Property behaviors

Joe Groff jgroff at apple.com
Tue Jan 19 17:10:15 CST 2016

> On Jan 19, 2016, at 2:46 PM, John McCall <rjmccall at apple.com> wrote:
>> On Jan 13, 2016, at 2:07 PM, Joe Groff via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> Thanks everyone for the first round of feedback on my behaviors proposal. I've revised it with the following changes:
>> - 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.
>> - 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.
>> - 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`.
> Syntax comments:
> 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].

I'm OK with using attribute syntax alongside the declaration approach.

> "var behavior" is really weird to me, and the <T> doesn’t seem to fit and is pretty redundant in the common case.  How about this:
>   "behavior" var-or-let "[" identifier-list "]" (identifier | "_") ":" identifier ("=" identifier)? ("where" generic-requirement-list)?
> So, for example,
>   behavior var [lazy] _ : T where T : IntegerLiteralConvertible { … }
> This is definitely taking the idea of “this is basically a macro” and running with it.  Think of the stuff between “behavior” and the optional “where” as being a pattern for the declaration.  So this pattern would match:
>   var [lazy] x: Int
> but not:
>   let [lazy] x: Int
> or:
>   var [lazy] x : Int = foo()

Good idea, I like this approach. However:

> The behavior list has to match exactly (or maybe as sets?).

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.

> The property name, if bound, expands to a string literal within the behavior.
> The type name is always a generic parameter.  This interferes with the ability to make a pattern that only matches a concrete type, but I think that’s okay.

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.

> The initializer name, if bound, expands to the original expression within the behavior.  Maybe it should be coerced to type T first?  Not sure.

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:

- 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.
- We add generic constraints from the behavior declaration(s) to the contextual type of the initializer.

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.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160119/ea2e79e5/attachment.html>

More information about the swift-evolution mailing list