This language feature seemed complicated to me at first glance. Then I read 
through Kevin’s treatment, and now it seems tremendously complicated. :-)

Property behaviors seem to be moving in the direction of formalizing the 
language’s property model, in that they interact with the property’s interface 
(accessors and more), storage, inheritance, delegation 
(logging/willSet/didSet), polymorphism (covariance), and probably more. Since 
the scope is so large, maybe this proposal can be split into parts?

What kind of language features would be needed to implement the 
(language-implemented) behaviors that we have now, ignoring the compiler’s 
blessing of syntax to make the implementation transparent?

The obvious way to think of behaviors is structs that contain the property’s 
storage, with interface methods providing access. If we tried to implement 
everything in Joe’s proposal directly with generic structs, what problems would 
be hit?

The first problem is the initializer closure: capturing `self` is a bad idea, 
but if the initializer just took `self` as an argument (if safe to do so), then 
the initializer could simply be stored in the “property box” with the downside 
of increased storage. Making this type-safe seems to require that box type also 
be generic over the type of the containing object, which is interesting. 
Lazy<Value>, MemoizationBox<Value>, Delayed<Value>, and Resettable<Value> can 
be straightforwardly implemented this way.

Synchronized<Value> can be as well: if `self` is available to be passed to the 
initializer, then it is available to grab a lock from. Of course here we start 
hitting the composition problems: you can write either 
Lazy<Synchronized<Value>> or Synchronized<Lazy<Value>>. Like Kevin said, what 
you really want is dispatch_once-like behavior: a single control value which 
means “uninitialized”, “being initialized”, or “initialized”.

Observed<Value> is another hint of a problem: if I understand correctly (I am 
really a Swift newbie), willSet and didSet can be overridden. Modeling that by 
composing a struct seems very difficult. A list of closures? Or closures which 
call the next one in the chain?

Also, you potentially want to be able to override the *whole property*, which 
is also a problem since it involves storage changes. And what you may really 
want is to override the whole property except for the observers.

I guess I’m implying that it should be possible to implement something with 
similar semantics and performance characteristics to property behaviors in a 
library, neglecting all special syntax. That prospect alone seems very 
intimidating. I wonder if there is a set of language features that would allow 
a library implementation, while still allowing properties to be thought of as a 
single “thing”? Even if those features are never implemented, it might make it 
clearer what specific magic is required for property behaviors to function. A 
non-exhaustive list:

1) overriding storage in a subclass while still vending the original interface 
to people using the object via a super type or a protocol
2) methods in the composed type that are overridable in the container type 
(willSet/didSet)
3) initializer method/closure that neither captures `self` nor takes up space 
in the instance when stored (i.e. acts like a method of the container type)
4) the proposed safety when composing multiple boxes in potentially 
incompatible orders

I think exploring what those features would look like in isolation might be 
illuminating. Of course, they may turn out to be overly generic and only useful 
in the context of properties.

-John
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to