# Pitch: Property Delegates

**URL:** <https://forums.swift.org/t/pitch-property-delegates/21895>\
**Category:** Pitches\
**Created:** [March 21, 2019, 9:30pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895 "2019-03-21T21:30:09Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![jberry](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jberry/32/6360_2.png) [@jberry](https://forums.swift.org/u/jberry)\
**Post date:** [March 22, 2019, 5:47pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/63 "2019-03-22T17:47:13Z")

</div>

> [@Preston\_Sumner](#):
>
> ```swift
> var x: Int via Lazy = 49
> 
> ```

I really like `via`. It's short, unique, and does a good job of suggesting the indirection.

---

<div class="post-metadata">

**Author:** ![Douglas\_Gregor](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/douglas_gregor/32/1362_2.png) [@Douglas\_Gregor](https://forums.swift.org/u/Douglas_Gregor)\
**Post date:** [March 22, 2019, 5:50pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/64 "2019-03-22T17:50:42Z")

</div>

> [@tkrajacic](#):
>
> One concern is that the composability has gone iiuc. So I can't specify e.g.
> 
> ```swift
> … by Atomic, Lazy
> 
> ```
> 
> So there will be a lot of Delegate types that just combine others? Got a new one – now you have to write 20 variants of it if you need other behavior composed (In reality I guess there will be a handful of common ones, so I am not sure this will be a big issue)

Composition is something we [weren't able to adequately solve with the property behaviors design](https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md#composing-behaviors) in 2015-2016, either. In particular, composing `Atomic` and `Lazy` is fraught, because composing them in the wrong order will result in surprisingly bad semantics. As natural as it is to want to compose delegates at the use site, that cautionary tale makes me thing it's better to have compositions described as specific delegate types.

Doug

---

<div class="post-metadata">

**Author:** ![Douglas\_Gregor](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/douglas_gregor/32/1362_2.png) [@Douglas\_Gregor](https://forums.swift.org/u/Douglas_Gregor)\
**Post date:** [March 22, 2019, 5:52pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/65 "2019-03-22T17:52:52Z")

</div>

> [@allevato](#):
>
> I'm not sure if this is already meant to be implied by the terminology in the proposal, but is this feature restricted to type members, or does it also apply to any `VarDecl` , including function-local and global variables?

Function-local and global variables are also supported; I've clarified this in the latest revision at [https://github.com/DougGregor/swift-evolution/blob/property-delegates/proposals/NNNN-property-delegates.md](https://github.com/DougGregor/swift-evolution/blob/property-delegates/proposals/NNNN-property-delegates.md).

Doug

---

<div class="post-metadata">

**Author:** ![pitiphong.p](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pitiphong.p/32/811_2.png) [@pitiphong.p](https://forums.swift.org/u/pitiphong.p)\
**Post date:** [March 22, 2019, 5:55pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/66 "2019-03-22T17:55:12Z")

</div>

Thank you for the explanation. I read the proposal after posting my question and understand how it would work now.

So do I understand correctly that the reason that it must be var is that the Property will be converted into a computed property in the end which is already require the var keyword not related to the Property Delegations concept itself?

---

<div class="post-metadata">

**Author:** ![David\_Smith](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/david_smith/32/37508_2.png) [@David\_Smith](https://forums.swift.org/u/David_Smith)\
**Post date:** [March 22, 2019, 5:58pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/67 "2019-03-22T17:58:25Z")

</div>

Ah maybe I misunderstood the question then. Couldn't you just make the $foo public and do $foo.addObserver(…)?

---

<div class="post-metadata">

**Author:** ![tkrajacic](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tkrajacic/32/1173_2.png) [@tkrajacic](https://forums.swift.org/u/tkrajacic)\
**Post date:** [March 22, 2019, 6:03pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/69 "2019-03-22T18:03:13Z")

</div>

> [@Douglas\_Gregor](#):
>
> As natural as it is to want to compose delegates at the use site, that cautionary tale makes me thing it's better to have compositions described as specific delegate types.

I completely understand that. It would just be a bit unfortunate if I want to package my own behavior in a delegate type, but also want the property to be observable for example, that I'd literally have to copy the implementation from the official one into my code as well.

I do understand that "copy code in" is oversimplified and actually the very reason the easy composability doesn't exist in the first place, but I just remember how simple it was in Objective-C to add `atomic` for example to the declaration of a property – and there it was.

I mean if I want to have a property be `Observable` (suppose this would be a possible delegate) then there would need to be an `ObservableAtomic`, `ObservableLazy`,… and so on. Maybe I'm overthinking this, but I suppose there will be delegates that will be very frequently used, and this means we'll need a LOT of variants.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [March 22, 2019, 6:03pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/70 "2019-03-22T18:03:55Z")

</div>

> [@David\_Smith](#):
>
> Ah maybe I misunderstood the question then. Couldn't you just make the $foo public and do $foo.addObserver(…)?

Yeah, it looks like that would work with no problem.

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [March 22, 2019, 6:17pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/71 "2019-03-22T18:17:50Z")

</div>

If we're going to bikeshed `by`, let's bikeshed it from first principles.

If we want to choose a keyword that reads well, we have to consider what is around that keyword. On the left (in the proposed syntax, at least), we have a type or property name which will usually be a noun, because the Swift API Design Guidelines state:

> - The names of other **types, properties, variables, and constants should read as nouns.**

But what belongs on the right side of the keyword? What sort of name should you give to a property delegate?

Many of the examples in this thread are adjectives—`Lazy`, `DelayedMutable`, `Copying` (participles are adjectives), `CopyOnWrite`, `Observable`, `Synchronized`, and `Indirect` all are. But `UnsafeMutablePointer` and `UserDefault` are nouns, and I think they may represent a category of delegates specifying where a property is stored. Imagine `DatabaseColumn` or `XPC`, for instance. Or `Box`, for that matter.

The `by` keyword works with some nouns, but not all, and doesn't really work with adjectives.

```swift
var foo: Foo by Lazy
var foo: Foo by DelayedMutable
var foo: Foo by Copying // This one's okay because you reinterpret it as a verb.
var foo: Foo by CopyOnWrite
var foo: Foo by Observable
var foo: Foo by Synchronized
var foo: Foo by Indirect

var foo: Foo by UnsafeMutablePointer
var foo: Foo by UserDefault
var foo: Foo by DatabaseColumn
var foo: Foo by XPC
var foo: Foo by Box // wut

```

The adjectives could be adapted into nouns by adding a suffix like `Property` or `Var`. If we did that, `in` would read pretty well; if we wanted a slightly more unique keyword, `within` or `inside` would work too.

```swift
var foo: Foo in LazyVar
var foo: Foo in DelayedMutableVar
var foo: Foo in CopyingVar
var foo: Foo in CopyOnWriteVar
var foo: Foo in ObservableVar
var foo: Foo in SynchronizedVar
var foo: Foo in IndirectVar

var foo: Foo in UnsafeMutablePointer
var foo: Foo in UserDefault
var foo: Foo in DatabaseColumn
var foo: Foo in XPC
var foo: Foo in Box

```

This might also make us rethink the metaphor we use to describe this feature: you could describe it as specifying a "container" to store the property inside, which might lead you to call this feature something like "property containers".

On the other hand, the nouns can usually be adapted into adjectives by adding some suffix too, although the appropriate suffix would vary by the exact nature of the noun. Adjectives would pair well with keywords like `is` or `but`:

```swift
var foo: Foo but Lazy
var foo: Foo but DelayedMutable
var foo: Foo but Copying
var foo: Foo but CopyOnWrite
var foo: Foo but Observable
var foo: Foo but Synchronized
var foo: Foo but Indirect

var foo: Foo but UnsafeMutablePointerStored
var foo: Foo but UserDefaultStoring
var foo: Foo but DatabaseColumnFetched
var foo: Foo but XPCBacked
var foo: Foo but Boxed

```

Adjectives would also read nicely in attribute position (unsurprising, since most attributes are adjectives and English word order puts adjectives before the nouns they're attached to). Using a `$` prefix as a strawman:

```swift
$Lazy var foo: Foo
$DelayedMutable var foo: Foo
$Copying var foo: Foo
$CopyOnWrite var foo: Foo
$Observable var foo: Foo
$Synchronized var foo: Foo
$Indirect var foo: Foo

$UnsafeMutablePointerStored var foo: Foo
$UserDefaultStoring var foo: Foo
$DatabaseColumnFetched var foo: Foo
$XPCBacked var foo: Foo
$Boxed var foo: Foo

```

However, this would have some undesirable features—particularly, if you needed to use `DelegateName(…)` syntax to initialize the delegate, the probably-very-complicated initialization code appears before the declaration rather than after. It would also be tempting to actually make these _be_ attributes, but that could be confusing because unlike normal attributes, you can only have one delegate per property.

I don't have any specific suggestion or proposal I want to push from this set; I just thought this might be a useful way to frame syntax discussions about this feature.

_(Note: Some of the syntaxes here were originally suggested by others, but I'm to blame for any bad opinions.)_

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 22, 2019, 6:23pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/72 "2019-03-22T18:23:24Z")

</div>

> [@tkrajacic](#):
>
> I completely understand that. It would just be a bit unfortunate if I want to package my own behavior in a delegate type, but also want the property to be observable for example, that I'd literally have to copy the implementation from the official one into my code as well.

You can just make the `value` property of the composite delegate type a delegate itself.

---

<div class="post-metadata">

**Author:** ![tkrajacic](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tkrajacic/32/1173_2.png) [@tkrajacic](https://forums.swift.org/u/tkrajacic)\
**Post date:** [March 22, 2019, 6:24pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/73 "2019-03-22T18:24:12Z")

</div>

I still find `via` to look favorable here. It can be used with nouns and verbs alike.

```
var foo: Foo via Lazy
var foo: Foo via DelayedMutable
var foo: Foo via Copying
var foo: Foo via CopyOnWrite
var foo: Foo via Observable
var foo: Foo via Synchronized
var foo: Foo via Indirect

var foo: Foo via UnsafeMutablePointer
var foo: Foo via UserDefault
var foo: Foo via DatabaseColumn
var foo: Foo via XPC
var foo: Foo via Box

```

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [March 22, 2019, 6:25pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/74 "2019-03-22T18:25:21Z")

</div>

> [@tkrajacic](#):
>
> It would just be a bit unfortunate if I want to package my own behavior in a delegate type, but also want the property to be observable for example, that I'd literally have to copy the implementation from the official one into my code as well.

You wouldn't need to copy the entire implementation. Remember that property delegates are also ordinary types, and it's okay to use them that way:

```swift
@propertyDelegate
struct SynchronizedLazy<Value> {
  var underlyingDelegates: Synchronized<Lazy<Value>>
  // initializer matches Lazy's
  init(initialValue: @escaping @autoclosure () -> Value) {
    underlyingDelegates = Synchronized(initialValue: Lazy(initialValue: initialValue()))
  }
  var value: Value {
    get { return underlyingDelegates.value.value }
    set { underlyingDelegates.value.value = newValue }
  }
}

```

---

<div class="post-metadata">

**Author:** ![tkrajacic](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tkrajacic/32/1173_2.png) [@tkrajacic](https://forums.swift.org/u/tkrajacic)\
**Post date:** [March 22, 2019, 6:25pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/75 "2019-03-22T18:25:29Z")

</div>

> [@John\_McCall](#):
>
> You can just make the `value` property of the composite delegate type a delegate itself.

Of course, stupid me! 🙄  
That actually sounds quite good, thx!

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 22, 2019, 6:27pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/76 "2019-03-22T18:27:54Z")

</div>

> [@beccadax](#):
>
> unlike normal attributes, you can only have one delegate per property.

I don't see why this is a problem. Many attributes are exclusive with each other, and many attributes will be exclusive with delegates however we spell them. It seems to me that having two syntaxes for modifying declarations (`@attribute` and `baremodifier`) is better than having three. It also seems we've already agreed that we shouldn't allow multiple delegates to be applied to the same declaration, so there's no compositionality argument against attributes, either.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [March 22, 2019, 6:40pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/77 "2019-03-22T18:40:54Z")

</div>

> [@beccadax](#):
>
> particularly, if you needed to use `DelegateName(…)` syntax to initialize the delegate, the probably-very-complicated initialization code appears before the declaration rather than after. It would also be tempting to actually make these _be_ attributes, but that could be confusing because unlike normal attributes, you can only have one delegate per property.

I don't think this syntax would be awkward. We already have attributes with arguments and this syntax looks fine on its own line when necessary. In fact I think this syntax has some distinct advantages. Placing modifiers _before_ the declaration itself reads better (IMO) and works better in multi-line declarations. There is a loose analogy with the backing property that is declared which is nice. Lastly, it provides a logical way for the syntax to support direct initialization of the backing property.

Here are some examples:

```swift
public $Lazy var foo: Int

// line wrapping
public $Lazy(closure: {42 })
var foo: Int

// different access levels
private $Lazy(closure: {42 })
public var foo: Int

// different access levels
public $Lazy = anExistingLazyDelegate
var foo: Int

// error: redundant initialization
public $Lazy = anExistingLazyDelegate
var foo: Int = 42

$UnsafeMutablePointer(mutating: addressOfAnInt)
var someInt: Int

```

---

<div class="post-metadata">

**Author:** ![SDGGiesbrecht](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sdggiesbrecht/32/4768_2.png) [@SDGGiesbrecht](https://forums.swift.org/u/SDGGiesbrecht)\
**Post date:** [March 22, 2019, 6:42pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/78 "2019-03-22T18:42:05Z")

</div>

> [@beccadax](#):
>
> If we're going to bikeshed `by` , let's bikeshed it from first principles.

I like this method of reasoning. The delegates are themselves type names, and nouns allow consistency. I like `through` or `via`, best. `by` is still the runner‐up. `in` and `but` feel imprecise and awkward to me.

```swift
var foo: Foo through LazyComputation // All right, this one is awkward to noun‐ify.
var foo: Foo through DelayedMutation
var foo: Foo through Copying
var foo: Foo via CopyOnWrite
var foo: Foo via Observation
var foo: Foo by Synchronization
var foo: Foo by Indirection

var foo: Foo through UnsafeMutablePointer
var foo: Foo through UserDefault
var foo: Foo via DatabaseColumn
var foo: Foo via XPC
var foo: Foo by Box

```

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [March 22, 2019, 6:42pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/79 "2019-03-22T18:42:53Z")

</div>

> [@John\_McCall](#):
>
> It also seems we've already agreed that we shouldn't allow multiple delegates to be applied to the same declaration, so there's no compositionality argument against attributes, either.

I have some sketchy ideas about how we might be able to handle composition using generic property delegates. If I have time to think them through this weekend and they work out ok I'll write them up.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 22, 2019, 6:54pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/80 "2019-03-22T18:54:28Z")

</div>

Is this going to be a sneaky form of higher-kinded types? 😄

Anyway, syntax only makes a difference for composition of delegates if you're relying on using a syntax which naturally orders the delegates (e.g. using successive `by` clauses), which seems _extremely_ subtle to be relying on — quick, which of `by Lazy by Atomic` or `by Atomic by Lazy` is the correct ordering? (The answer is neither, you need a custom implementation — unless `Atomic` unconditionally works by taking a lock, in which case whichever of those that puts `Atomic` on the outside is correct.)

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [March 22, 2019, 7:01pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/81 "2019-03-22T19:01:26Z")

</div>

> [@John\_McCall](#):
>
> Is this going to be a sneaky form of higher-kinded types? 😄

The ideas are still sketchy, but hopefully it wouldn't need them because then it would only be a distant dream, not something that might work in the near future. 😉

> [@John\_McCall](#):
>
> Anyway, syntax only makes a difference for composition of delegates if you're relying on using a syntax which naturally orders the delegates (e.g. using successive `by` clauses), which seems _extremely_ subtle to be relying on — quick, which of `by Lazy by Atomic` or `by Atomic by Lazy` is the correct ordering? (The answer is neither, you need a custom implementation — unless `Atomic` unconditionally works by taking a lock, in which case whichever of those that puts `Atomic` on the outside is correct.)

The general idea is to use a small number of protocols to allow delegates to declare how they participate in composition. Some delegates would simply not be directly composable and would still require manual composition. It wouldn't cover all cases of composition but maybe it would be able to cover a lot of common cases in a safer way (i.e. as long as the delegates involved are well designed composition wouldn't result in surprising behavior).

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 22, 2019, 7:03pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/82 "2019-03-22T19:03:23Z")

</div>

Okay. If it's declarative if some way then it should work regardless of syntax, right? So it's purely additive to this proposal.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [March 22, 2019, 7:24pm UTC](https://forums.swift.org/t/pitch-property-delegates/21895/83 "2019-03-22T19:24:28Z")

</div>

> [@John\_McCall](#):
>
> Okay. If it's declarative if some way then it should work regardless of syntax, right? So it's purely additive to this proposal.

If it works out and we intend to pursue it I think it may motivate modifying the design of this proposal to use a `PropertyDelegate` protocol instead of an attribute (even if composition was left as a future direction).

[Previous page](https://forums.swift.org/t/pitch-property-delegates/21895.md?page=3)

[Next page](https://forums.swift.org/t/pitch-property-delegates/21895.md?page=5)
