Do we really need to access the backing storage? I mean the whole idea is to "accommodate several important patterns for properties" and correct me if I'm wrong, the backing storage is going to be private
or internal
in most cases. There aren't many use-cases that we really need to access the backing storage.
That being said, this feature cannot stop anyone from writing this code:
var fooStorage: Lazy<Int> = .init(initialValue: 42)
var foo: Int {
get { return fooStorage.value }
set { fooStorage.value = newValue }
}
The whole idea of having $
as prefix of backing storage is cool, but I think it's just overdoing it.
If the backing storage needs to be exposed, I prefer it being defined explicitly rather than being synthesized implicitly. Either-way delegation would still be possible:
@staticAttribute(usage: [.property])
struct Delegated<Delegate: PropertyDelegate> {
var delegate: Delegate
init(to delegate: Delegate) { ... }
}
class Test {
public var dataStorage = Lazy<Data>()
@Delegated(to: dataStorage)
private var data: Data
}
Another approach would be to define the synthesized storage with different access-level. (but my guess is, it will add a lot of complexities to the compiler since using $
as prefix of variable is not allowed):
class Test {
@Lazy var data1: Data
private var $data2: Lazy<Data>
@Lazy var data2: Data
}
will result in:
class Test {
internal var $data1 = Lazy<Data>()
internal var data1: Data {
mutating get { return $data1.value }
set { $data1.value = newValue }
}
private var $data2 = Lazy<Data>()
internal var data2: Data {
mutating get { return $data2.value }
set { $data2.value = newValue }
}
}