Hi all,
Based on the discussions in the property delegates pitch and review, it seems that we should push further on the composition angle. So, I had an idea that could use some refinement.
Let's start with the notion that we have two trivial property delegate types, A and B:
@propertyDelegate
struct A<T> {
  var value: T
}
@propertyDelegate
struct B<T> {
  var value: T
}
We could allow multiple property delegates to be composed. That composition effectively has to be linear, nesting one delegate instead the other. The synthesized getter/setter would look through the full chain of .value, e.g.,
@A @B var foo: Int
becomes:
var foo_storage: A<B<Int>>
var foo: Int {
  get { return foo_storage.value.value }
  set { foo_storage.value.value = newValue }
}
How do we get to the API for A and B? Well, the prefix $ from the proposal could be repurposed to mean "suppress one .value", so $foo refers to the foo_storage.value (i.e., the B<Int>) and $$foo refers to foo_storage (i.e., the A<B<Int>>) directly.
You could take this one step further, such that value members that themselves have attached delegates could be considered to be composed. For example:
@propertyDelegate
struct C<T> {
  @B var value: T
}
@C var bar: Int
we could say that bar is translated to:
var bar_storage: C<Int>
var bar: Int {
  get { return bar_storage.$value.value }
  set { bar_storage.$value.value = newValue }
}
Then, $bar is the B<Int> and $$bar is the C<Int>. It gives the same expressiveness as the delegateValue property in the current proposal, but bases it on the same "suppress .value" unwrapping mechanism as composition.
I think I like this approach because it keeps the conciseness of $ for the common case (no composition, no tricks), allows composition while maintaining a direct translation model (nesting + multiple .values), and makes the delegateValue effect not feel like a one-off trick.
I haven't tried to hack up an implementation, but it seems straightforward. Thoughts?
Doug