[swift-evolution] [Proposal] Property behaviors
Wallacy
wallacyf at gmail.com
Thu Jan 14 12:43:09 CST 2016
I really liked this idea:
x..resettablet.reset()
I can see that when typing the second dot, the autocomplete offering me all
behaviors available. ;)
And thinking a little, may the `pipe` can be used to declaration :
var |lazy| number = 1243
The Square brackets is good, but feels like array.
And for multiple behaviors, we can use the "*>*" to infer the "direction"
of the "composability":
var |lazy>observed| observedLazy = expensiveExpression() {
didSet { print("\(oldValue) => \(observedLazy)") }
}
Em qui, 14 de jan de 2016 às 02:08, Joe Groff via swift-evolution <
swift-evolution at swift.org> escreveu:
> On Jan 13, 2016, at 7:13 PM, Félix Cloutier <felixcca at yahoo.ca> wrote:
>
> I started by reading the examples and I was very confused. This suggests
> to me that if you've never seen a var behavior before, you are going to
> wonder what the hell is going on. :-)
>
>
> This is good feedback, thanks!
>
> Notable points of confusion:
>
>
> - it's confusing to me that `self` is the containing type and the
> behavior name is the "behavior's self".
>
>
> Others have noted this too. Would it be less confusing if one had to
> explicitly name the "container" as a member, e.g.:
>
> var behavior synchronized {
> container var parent: Synchronizable
> base var value: Value
>
> get {
> return parent.withLock { value }
> }
> set {
> parent.withLock { value = newValue }
> }
> }
>
>
>
> - The `initializer` special field feels absolutely magic. Has anything
> else been considered, like an init param that has either a Value or an
> autoclosure returning one? (If we don't want to capture self, aren't we in
> for problems capturing self from accessors anyway?)
>
>
> An `init` parameter covers use cases where the initializer expression is
> used only during initialization, but doesn't let you use the initializer
> after initialization, which is necessary for `lazy`, `resettable`, and
> other use cases. Even with @autoclosure, it seems to me that, without
> `initializer`, we'd need to allocate per-property storage for the
> initializer expression to use it later, which is something I'd like to
> avoid.
>
>
> - I see (after reading it) that `var behavior foo<Value>: Value` means
> that foo "applies to"/"wraps" Value, but I find it confusing to use a
> syntax more typically associated with "extends" or "implements" or "is a".
>
>
> Would it be less confusing if the type of the property were implicit? In
> discussion with Brent, I suggested a model where you say:
>
> var behavior foo { ... }
>
>
> and if you want to constrain the types of properties that can instantiate
> the behavior, you use a where clause:
>
> var behavior foo where Value: NSCopying { ... }
>
> which optimizes the common case (no constraint), and might be easier to
> read.
>
> Questions:
>
>
> - Can a behavior have generic parameters that can't be inferred? Could
> I write, say, [fooable<Int>]?
>
>
> No, the generic parameters are only used to generalize the property type.
>
>
> - What is the tradeoff between `eager` and `deferred`? Is it "only"
> that `deferred` side effects happen at the mercy of the behavior?
> - If so, isn't it a problem that behaviors aren't intrinsically
> explicit about whether they defer initialization? I can see that causing
> very subtle bugs.
>
>
> The tradeoff is that an 'eager' initialization can be used in `init`, but
> that means that an initializer expression can't refer to `self`, because
> `self` is not fully initialized. This is how initializer expressions always
> work today:
>
> struct X {
> var x = 0, y = 1
> var z = x + y // Error
> }
>
> A deferred initialization can only be evaluated *after* init, but because
> of that, it can refer to `self`, which people would like to be able to do
> with `lazy` (but currently can't):
>
> struct X {
> var x = 0, y = 1
> lazy var z = x + y // Theoretically OK
> }
>
>
> Concerns:
>
>
> - It looks like if you had a [resettable, observable] property,
> calling resettable.reset() would change the value from under `observable`'s
> feet.
>
>
> True. An unfortunate consequence of these things being user-defined is
> that there will always be "wrong" orderings of them. I'm not sure how much
> we can do about that.
>
>
> Comments:
>
>
> - While it might be true that square brackets work better with other
> declarations that could eventually have behaviors, "var behavior" doesn't
> really lend itself to that kind of extensibility. Are we steering towards
> "func behavior", "class behavior", etc? Is it a problem if we are?
>
>
> Possibly. Note that square brackets are necessary even only for `var`,
> because you can declare a destructuring binding `var (x, y) = tuple`.
>
>
> - I'd like to point out that the memoization example is a let variable
> with a behavior, which is explicitly forbidden by the current proposal.
>
>
> Thanks, missed that.
>
>
> Finally, I would like to throw the idea of "foo..resettable" to access
> foo's resettable behavior (or foo..reset() doing optionally-qualified
> lookup on foo's behavior methods).
>
>
> Not a bad suggestion.
>
> Thanks again for the feedback!
>
> -Joe
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160114/e497970c/attachment.html>
More information about the swift-evolution
mailing list