[swift-evolution] [Proposal] Property behaviors

Joe Groff jgroff at apple.com
Thu Jan 21 20:16:55 CST 2016


> On Jan 21, 2016, at 1:23 PM, Wallacy <wallacyf at gmail.com> wrote:
> 
> Will property behaviors work on computed properties? Because for now, we can change a storage to a computed property and a computed for a storage property without breaking anything.

I'm not sure exactly what you mean, but property behaviors are (by default) implementation details, so you can change the implementation of a property to computed to stored to behaviors without breaking API. If you publish a behavior as public, you'd be promising to use that behavior as part of the implementation forever.

-Joe

> 
> Em qui, 21 de jan de 2016 às 00:44, Joe Groff via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> escreveu:
> 
> > On Jan 20, 2016, at 6:12 PM, Michel Fortin <michel.fortin at michelf.ca <mailto:michel.fortin at michelf.ca>> wrote:
> >
> > Le 19 janv. 2016 à 21:38, John McCall via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> a écrit :
> >
> >> One of my worries about this proposal in general is that you’ve listed out half-a-dozen different uses and every single one seems to require a new twist on the core semantics.
> >
> > That's my general feeling too about this proposal. I just didn't know how to express what you said above.
> 
> I *did* somewhat strategically pick my examples to try to cover the breadth of different things I see someone wanting to do with this feature.
> 
> >
> > To me this proposal feels like it's is about trying to find a solution to multiple problems at once. A new problem arise that looks like it could be solved by a behaviour, so the behaviour feature expands to accommodate it. It looks like the wrong approach to me.
> >
> > The correct approach in my opinion would be to try to make various parts of this proposal standalone, and allow them to combine when it makes sense. For instance, if you wanted to define a standalone feature for defining custom accessors that can be used everywhere, you wouldn't come with something that requires a behaviour annotation at the variable declaration. You'll come with something simpler that might looks like this:
> >
> > custom_acccessor willSet<T>(newValue: T) { // define a custom accessor...
> >       set { // ... by redefining the setter...
> >               willSet(newValue) // ...inserting a call to the accessor here...
> >               currentValue = newValue // ...before calling the underlying setter
> >       }
> > }
> > custom_acccessor didSet<T>(oldValue: T) {
> >       set {
> >               let oldValue = currentValue
> >               currentValue = newValue
> >               didSet(oldValue)
> >       }
> > }
> > custom_acccessor willChange<T>(newValue: T) {
> >       willSet {
> >               if currentValue != newValue {
> >                       willChange(newValue)
> >               }
> >       }
> > }
> >
> > Then at the declaration point you just directly use the globally accessible accessor:
> >
> >       var myvar: Int {
> >               willChange { print("will change to \(newValue)") }
> >       }
> >
> > This fulfills at least one of the use cases. Can't we do the same treatment to each proposed use cases and see if there are other parts that can stand on their own?
> 
> I considered this approach. It works for behaviors that don't need to control a property's storage and only change the property's access behavior. To be fair, that covers a lot of ground, including things like observing, NSCopying, resetting, and locking synchronization. We would still need a feature, which could certainly be a different one, to generalize annotations that control the storage policy for decorated properties, which could cover things like laziness, indirect storage, unowned/weak-ness, dirty-tracking, C-style atomics, and pointer addressability—basically, anything where a plain old stored property of the API type isn't sufficient. (You could even throw get/set in this bucket, if you wanted to be super reductionist.) Finally, there's the feature to add operations on a *property* independent of its *type*, which interacts usefully with both other features—you need a way to reset a resettable or lazy property; maybe you want to bypass a synchronized property's lock in one place, etc. We'd like to improve on the "classic" answer of exposing an underlying ivar or property in these cases. If you want to break it down in micro-features, I guess there are three here:
> 
> 1. Factoring out storage patterns,
> 2. Factoring out accessor patterns, and
> 3. Adding per-property operations.
> 
> (1) tends to be tightly coupled with (2)—if you're controlling storage, you almost certainly want to control the accessors over that storage. And (3) is useful with both (1) and (2). If there are separate features to be factored out here, I think they're very entangled features.
> 
> -Joe
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>

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


More information about the swift-evolution mailing list