[swift-evolution] [Proposal] Property behaviors

Félix Cloutier felixcca at yahoo.ca
Thu Dec 17 22:17:39 CST 2015


I think I agree with you. On a Synchronized<T>, all you have to do is implement a get<U>(access: T -> U) -> U to get almost the same syntax that Michel suggested.

(Can you do object[] { /* closure */ } or even object { /* closure */ } if you have a subscript that only accepts a closure? That could be interesting...)

On a semi-related note to your semi-related note, I'm not sure how I feel about the "foo.lazy" syntax because of the name resolution problems. I'm also not a fan of "`foo.lazy`"; I don't know any language that forces you to use the identifier escape to access built-in features.

In general, I think that accessing the behavior object should be restricted to the private scope. IMHO, if we want to restrict usage on behavior objects, the most obvious thing to do is to use a call-like syntax (since calls aren't assignable).

I'm thinking of something like `<lazy>(foo)` and `var<lazy> foo: Int` (for symmetry) to access the behavior object. I don't think that any expression can start with a < right now, and this would allow an independent namespace for behaviors. I don't have a strong opinion on that though.

Additionally, if behaviors become types instead of keywords, perhaps even within their own namespace they should follow regular type naming conventions. This could reduce namespace friction (you could always refer to them through their qualified name if they were shadowed).

> Le 17 déc. 2015 à 22:47:48, Kevin Ballard via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> Good point. I'm also inclined to say that Michel's motivating example (of a property that requires going through a `synchronized` accessor) would be better modeled just as a type Synchronized<Value> that exposes the `synchronized` accessor. No need for behaviors, you just say
> 
> var data: Synchronized<T> = ...
> 
> Behaviors are interesting because they affect how normal property access works. Properties that don't expose normal property accessors aren't really properties at all.
> 
> The only real downside to the Synchronized<Value> type is there's no way to prevent anyone from copying the value (it could be a class, but then you're paying for the overhead of using a separate object). This same limitation is also one of the problems with adding an Atomic<T> type, which is something I would dearly love to have.
> 
> On a semi-related note, we should say up-front that accessing behaviors on properties (e.g. with `foo.lazy`) _cannot_ be used to extract the behavior type as a value. The only thing you can do with this is calling a method on it or accessing a property. So no saying `let foo = data.lazy`. This limitation would be more obvious if we use an alternative behavior accessor syntax.
> 
> -Kevin Ballard
> 
> On Thu, Dec 17, 2015, at 07:00 PM, Félix Cloutier via swift-evolution wrote:
>> I find that Michel Fortin's idea for subscript-less behaviors is very cool, but it also has an impact on composition. It seems to me that any behavior that doesn't implement a subscript would need to be the outer-most behavior, and it could not easily compose with any other subscript-less behavior.
>> 
>> Félix
>> 
>>> Le 17 déc. 2015 à 20:23:46, Joe Groff via swift-evolution <swift-evolution at swift.org> a écrit :
>>> 
>>> 
>>>> On Dec 17, 2015, at 3:22 PM, Russ Bishop <xenadu at gmail.com> wrote:
>>>> 
>>>> My first assumption is that behaviors separate broadly into a couple of categories:
>>>> 
>>>> 1. Eager and uncorrelated. The logging example is a good one. A logging behavior probably doesn’t care about anything else, it just wants to run as early as possible to write the log output.
>>>> 2. Ordered or correlated. These have composability issues.
>>>> 3. Un-eager. didSet/willSet kind of behaviors that want to run after all behaviors of type #2 have run.
>>>> 
>>>> I’m trying to think if there is a way to declare the kind of behavior you have and what that would mean for composability and overriding because the compiler would be free to run all behaviors of type #1 first (unordered), then a single #2 behavior, then all the #3 behaviors (unordered), reducing the problem to specifying how ordered behaviors… er… “behave”. Perhaps in that case you’ll just have to manually implement a behavior that calls the desired behaviors. 
>>>> 
>>>> For overriding, as long as there is only one ordered behavior involved, all the other behaviors can execute in the appropriate “phase” without issue (all inherited eager behaviors first, etc).
>>> 
>>> This is a great analysis. Kevin made a similar observation. If we went in the direction of a dedicated `behavior` declaration, then it'd be reasonable to declare the behavior's kind up front, which would influence its composition behavior.
>>> 
>>> -Joe
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list