I think this is a good model. It puts the control in the hands of the author of the property wrapper type.
Presumably, this follows the rules of definite initialization, the same way as we do for assignments to foo becoming initializations when possible.
Your intent here is to do a sequence of .wrappedValue's up to the one .wrapperValue? I'm not sure if I want that or the outermost .wrapperValue, and would want use cases.
& already has an established meaning for inout. We shouldn't overload the existing syntax to mean an arbitrary binding, or we'll introduce more type checking ambiguities.
FWIW, the original proposal was either internal or "access level of the original property", whichever was more restrictive. I think I'd like to get back to that.
@Douglas_Gregor when do you think the next review round will be kicked off? Before that we should have discussed the issue with valuementioned upthread and if we should rename it so it unlikely collides when @dynamicMemberLookup is used. I proposed wrappedValue.
Since the whole access is routed through that property, it will also require you to provide a setter if you want your property wrapper to be settable. But even that example you wrote feels redundant to me and I‘d rather stick with the current design where this property is optional to implement.
I want the following example to work, even in a world where $foo is only available when wrapperValue is defined.
@propertyWrapper
struct Wrapper<V> {
let value: V
var wrapperValue: Wrapper { return self }
init(initialValue v: V) { self.value = v }
}
extension Wrapper where V: BinaryInteger {
func valuePlus3() -> V { return value + 3 }
}
struct S {
@Wrapper var x: Int
}
let s = S(x: 4)
print(s.x) // 4
print(s.$x.valuePlus3()) // 7
I meant mutable by settable. If your example had another mutating member, you wouldn‘t be able to use it with your current rules and the way you defined wrapperValue.
That's fine. If a mutable func or a var property were added, then obviously a setter would be required. That's no different than any other struct property whose properties are mutable in some way.
Correct, the only advantage I see in requiring explicit wrapperValue is that you can limit the access to the theoretically mutable stored property to be read only. However if we‘d require it, it could lead to confusion with wrappedValue as the difference is a single character in the middle (assuming that we‘d rename value). To me it‘s not a big deal, but I don‘t know about other if they see wrappedValue and wrapperValue.
I am not an advocate of forcing wrapperValue to exist to get access to $foo. I just want to clarify that it will still be possible, even if it means wrapperValue just returns self.
Could we please get a post listing the current syntax as implemented in the latest toolchain for 5.0.x and the Xcode 11 beta? wrapperValue isn't doing anything for me in the beta, and neither is delegateWrapper.
I did. Hence the example I posted above. I just want confirmation that this will work after any changes are implemented. Frankly, it's getting rather hard to determine which behavior is expected or missing. The two implementations and the proposal have diverged from each other.
The toolchain from June 7 does not recognize @propertyWrapper. If there are changes which have not yet made it into a toolchain, I don't have a way to test them.
@Douglas_Gregor I may have missed responses to this question, but is anything being done to allow direct initialisation of a property wrapper value when its initialiser has other arguments? Right now, as soon as we need extra arguments to a property wrapper, we can't directly initialise the property.
I want to be able to write:
@MyPropertyWrapper(name: "test") var property = 6
But I'm forced to use:
@MyPropertyWrapper(name: "test", initialValue: 6) var property: Int
This works just fine with Xcode 11 included toolchain on Catalina.
@propertyWrapper
struct Test {
// I propose to rename it to `wrappedValue`
let value: Int
// Should be `wrapperValue`.
var delegateValue: String { "<\(value)>" }
init(initialValue: Int) {
self.value = initialValue
}
}
struct Foo {
@Test var number = 42
}
let foo = Foo()
print(type(of: foo.$number), foo.$number) // String <42>