Cleaning up

defer runs a statement, or the statements of defer do ... end, when the block that holds it ends, however it ends: at its end, through a return, a break, or a continue, when a ? passes an error on, or after a runtime error such as a panic. The deferred code of a block runs in the reverse of the order it was met, and only the code whose defer was reached runs:

func save(str path, str text) Result[int] do
    print("saving")
    defer print("done saving")
    int written = write_all(path, text)?
    return Result.OK(written)
end

The code is a function of its own, made when the defer runs: it uses and can change the variables around it as they are when it runs, as other functions written there do, and it cannot return. A defer in a loop's body runs at the end of each pass. exit ends the program without running deferred code.

with gives names to values that must be closed, and calls each one's close method when its block ends, however it ends, the last first:

with input = open_reader(source)?, output = open_writer(target)? do
    copy(input, output)
end

Each value is ready, and will be closed, before the next is made, so a ? that fails for the second closes the first. The type of each name is the type of its value, which must have a close(self) method.