Combined SE-0366 (third review) and SE-0377 (second review): rename `take`/`taking` to `consume`/`consuming`

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.

2 Likes