I'd rather we just stick with read
and modify
.
I don't like yield set
— the modify operation is not a version of set
with coroutines. It is an operation used for both reading and writing, whereas get
is solely for reading and set
is solely for writing. A more accurate term would be yield get set
.
I also think read
and modify
are better because they're more familiar terms. Even though they aren't officially available, they are used in the source code of the standard library and in other prominent libraries (both official and unofficial) and they have a significant impact on ARC performance, so many Swift programmers are already familiar with the terms.
We could add read
and modify
without making source-breaking changes by adding an attribute:
@coroutineAccessors
var x: Int { ... }
@coroutineAccessors
would indicate to the parser that read
and modify
can be used in a computed variable's body. (Of course, the actual name of the attribute can be debated.) If read
or modify
are used in a variable's body but the variable isn't marked @coroutineAccessors
, then we could present a Fix-It that adds the attribute.
Alternatively, if we don't like the idea of an attribute that changes how a declaration is parsed, we could make coroutineAccessors
an argument:
var(coroutineAccessors) x: Int { ... }
Of course, neither of these are ideal, but they're good enough to get us to Swift 7.
One pain point that has been brought up with the current _read
and _modify
accessors is that the fact that you can't yield from within a closure. Would it be possible to have an API that lets you work around this?
Maybe something like this?
var x: X {
read {
yield withCoroutineContinuation[] { continuation in
lockedX.withLock { x in
continuation.yield(x)
}
}
}
}
I also think that the proposal should specify how modify
works with property requirements declared on protocols.