Skip to content

Commit a7fa8dc

Browse files
committed
Add some clarifications based on @dabrahams' feedback.
1 parent 1bcf9dd commit a7fa8dc

File tree

1 file changed

+54
-48
lines changed

1 file changed

+54
-48
lines changed

proposals/XXXX-property-behavior-decls.md

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ x = 1 // Prints nothing
386386
x = 2 // Prints 1 => 2
387387
```
388388

389+
(Note that, like `didSet`/`willSet` today, neither behavior implementation
390+
will observe changes through class references that mutate a referenced
391+
class instance without changing the reference itself.)
392+
389393
### Synchronized Property Access
390394

391395
Objective-C supports `atomic` properties, which take a lock on `get` and `set`
@@ -510,9 +514,42 @@ aspects of a property definition using the behavior:
510514
is evaluated when the binding is semantically loaded from (in other words,
511515
when its getter is called).
512516

517+
Inside a behavior declaration, `self` is implicitly bound to the value that
518+
contains the property instantiated using this behavior. For a freestanding
519+
property at global or local scope, this will be the empty tuple `()`, and
520+
for a static or class property, this will be the metatype. Within
521+
the behavior declaration, the type of `self` is abstract and represented by the
522+
implicit generic type parameter `Self`. Constraints can be placed on `Self`
523+
in the generic signature of the behavior, to make protocol members available
524+
on `self`:
525+
526+
```swift
527+
protocol Fungible {
528+
typealias Fungus
529+
func funge() -> Fungus
530+
}
531+
532+
behavior var [runcible] _: Value
533+
where Self: Fungible, Self.Fungus == Value
534+
{
535+
get {
536+
return self.funge()
537+
}
538+
}
539+
```
540+
541+
Lookup within `self` is *not* implicit within behaviors and must always be
542+
explicit, since unqualified lookup refers to the behavior's own members. `self`
543+
is immutable except in `mutating` methods, where it is considered an `inout`
544+
parameter unless the `Self` type has a class constraint. `self` cannot be
545+
accessed within inline initializers of the behavior's storage or in `init`
546+
declarations, since these may run during the container's own initialization
547+
phase.
548+
513549
Definitions within behaviors can refer to other members of the behavior by
514550
unqualified lookup, or if disambiguation is necessary, by qualified lookup
515-
on the behavior's name:
551+
on the behavior's name (since `self` is already taken to mean the containing
552+
value):
516553

517554
```swift
518555
behavior var [foo] _: Value {
@@ -523,11 +560,12 @@ behavior var [foo] _: Value {
523560
}
524561

525562
mutating func update(x: Int) {
526-
foo.x = x // Disambiguate reference to behavior storage
563+
[foo].x = x // Disambiguate reference to behavior storage
527564
}
528565
}
529566
```
530567

568+
531569
If the behavior includes *accessor requirement declarations*, then the
532570
declared accessor names are bound as functions with labeled arguments:
533571

@@ -548,38 +586,6 @@ behavior var [fakeComputed] _: Value {
548586
Note that the behavior's own *core accessor* implementations `get { ... }`
549587
and `set { ... }` are *not* referenceable this way.
550588

551-
Inside a behavior declaration, `self` is implicitly bound to the value that
552-
contains the property instantiated using this behavior. For a freestanding
553-
property at global or local scope, this will be the empty tuple `()`, and
554-
for a static or class property, this will be the metatype. Within
555-
the behavior declaration, the type of `self` is abstract and represented by the
556-
implicit generic type parameter `Self`. Constraints can be placed on `Self`
557-
in the generic signature of the behavior, to make protocol members available
558-
on `self`:
559-
560-
```swift
561-
protocol Fungible {
562-
typealias Fungus
563-
func funge() -> Fungus
564-
}
565-
566-
behavior var [runcible] _: Value
567-
where Self: Fungible, Self.Fungus == Value
568-
{
569-
get {
570-
return self.funge()
571-
}
572-
}
573-
```
574-
575-
Lookup within `self` is *not* implicit within behaviors and must always be
576-
explicit, since unqualified lookup refers to the behavior's own members. `self`
577-
is immutable except in `mutating` methods, where it is considered an `inout`
578-
parameter unless the `Self` type has a class constraint. `self` cannot be
579-
accessed within inline initializers of the behavior's storage or in `init`
580-
declarations, since these may run during the container's own initialization
581-
phase.
582-
583589
### Nested Types in Behaviors
584590

585591
Behavior declarations may nest type declarations as a namespacing mechanism.
@@ -681,28 +687,28 @@ accessor-requirement-decl ::=
681687

682688
An accessor requirement declaration looks like, and serves a similar role to,
683689
a function requirement declaration in a protocol. A property using the
684-
behavior must supply an implementation for each of its accessor requirements.
685-
The accessor names (with labeled arguments) are bound as functions within
686-
the behavior declaration:
690+
behavior must supply an implementation for each of its accessor requirements
691+
that don't have a default implementation. The accessor names (with labeled
692+
arguments) are bound as functions within the behavior declaration:
687693

688694
```swift
689695
// Reinvent computed properties
690-
behavior var [computed] _: Value {
691-
accessor get() -> Value
692-
mutating accessor set(newValue: Value)
696+
behavior var [foobar] _: Value {
697+
accessor foo() -> Value
698+
mutating accessor bar(bas: Value)
693699

694-
get { return get() }
695-
set { set(newValue: newValue) }
700+
get { return foo() }
701+
set { bar(bas: newValue) }
696702
}
697703

698-
var [computed] foo: Int {
699-
get {
704+
var [foobar] foo: Int {
705+
foo {
700706
return 0
701707
}
702-
set {
703-
// Parameter gets the name 'newValue' from the accessor requirement
708+
bar {
709+
// Parameter gets the name 'bas' from the accessor requirement
704710
// by default, as with built-in accessors today.
705-
print(newValue)
711+
print(bas)
706712
}
707713
}
708714

@@ -763,7 +769,7 @@ a behavior declaration does not provide at least a getter.
763769

764770
### Using Behaviors in Property Declarations
765771

766-
Property declarations gain the ability to declare a behavior,
772+
Property declarations gain the ability to instantiate behavior,
767773
with arbitrary accessors:
768774

769775
```text

0 commit comments

Comments
 (0)