Pitch: Property Delegates

Those are some great thoughts and thinking out of the box. I've been pondering over if this could be related to the ideas from Key-Path Member Lookup. There seems to be some overlap and we should consider if these two proposals could be different sides of a same, yet undefined, abstraction.

It's a really wild idea, but one could implement Lazy as a @keyPathMemberLookup type:

@keyPathMemberLookup
enum Lazy<Value> {
    case uninitialized(() -> Value)
    case initialized(Value)

    init(initialValue: @autoclosure @escaping () -> Value) {
        self = .uninitialized(initialValue)
    }

    var value: Value {
        mutating get {
            switch self {
            case .uninitialized(let initializer):
                let value = initializer()
                self = .initialized(value)
                return value
            case .initialized(let value):
                return value
            }
        }
        set {
            self = .initialized(newValue)
        }
    }

    subscript<U>(keyPathMember keyPath: WritableKeyPath<T, U>) -> U {...}
}

In which case the declaration would be as simple as

var name: Lazy<String>

while still getting the underlying type API through the property.

name.isEmpty

The limitation of @keyPathMemberLookup is that it does not support methods in the current proposal, but one would expect that to be possible in future.

There is also a question on how to do the memberwise initializer and if the value should be exposed, but those seem to be solvable problems.

1 Like