Personally, I expect to use these modifiers a lot. Maybe not quite as much as std::move
, but they will certainly be important tools when working on real-time graphics in Swift. So I’d be happy with shorter forms in which punctuation played a more prominent role.
Punctuation could also address @John_McCall’s points:
Defining &
to mean “operate on this binding” (much like how $
means “operate through this property wrapper”) could make these feel more closely related.
My suggestion is to drop the imperatives entirely and embrace the dichotomy between expressions and declarations:
protocol Renderable {
func appendDisplayList(to frame: inout Frame) // familiar
}
struct Renderer {
func render(_ frame: inout(let) Frame) // f.k.a. `borrow Frame`
func releaseResources(for frame: in Frame) // f.k.a. `consume Frame`
}
class World {
var entities: [any Renderable]
func draw(in renderer: Renderer) {
let frame = Frame()
for entity in entities {
entity.appendDisplayList(to: &frame)
}
renderer.render(&frame)
renderer.releaseResources(for: &frame)
// could also do _ = &frame
}
Do we really need syntax to distinguish between lending and forfeiting at the call site? I don’t think it can be ambiguous as to which operation applies. Anyone familiar with inout
parameters can immediately apprehend that &x
operates on the binding named x
, not the value held within it, and why render(&Frame())
doesn’t work.