Expanding on that thought, this is the alternative for pitch examples using nesting instead of "move".
The nesting alternative
Example from the pitch:
How we can do it instead:
func test() {
var x: [Int] = getArray()
// x is appended to. After this point, we know that x is unique. We want to
// preserve that property.
x.append(5)
// We create a new variable y so we can write an algorithm where we may
// change the value of y (causing a COW copy of the buffer shared with x).
do {
var y = x
longAlgorithmUsing(&y)
// We no longer use y after this point, so move it when we pass it off to
// the last use.
consumeFinalY(y)
}
// x will be unique again here.
x.append(7)
}
Another example from the pitch:
How we can do it instead (pseudocode):
func useX(_ x: SomeClassType) -> () {}
func consumeX(_ x: __owned SomeClassType) -> () {}
func f() {
let other = do {
let x = ...
useX(x)
return x
} // x's lifetime ends
// other is a new binding used to extend the lifetime of x
useX(other) // other is used here... no problem.
consumeX(other) // other is used here... no problem.
}
The second example is more interesting as it asks for the value of "do {...}" block, something which is not currently possible (*):
let other = do {
let x = ...
useX(x)
return x
} // `x` lifetime ended
// `x` is moved to `other`
We don't have this today (*), but hopefully we will have it at some point (along with other statements like "if" and "switch" used as expressions).
Am I missing something obvious on why move
is significantly better than nesting? It feels a bit like "goto" compared to more structured alternatives.
(*) Edit: in fact it is possible today, just using a closure:
let other = { () -> ... in
let x = ...
useX(x)
return x
}() // `x` lifetime ended
// `x` is moved to `other`
but it would be nice if "do" operator supported it as well (or better! without extra brackets and type annotations).