Skip to content

Defer, Drop and Move

Calibre supports defer and defer return for code that should run when the current scope or function is about to finish.

const main => fn => {
defer return print("leaving function");
=> {
defer print("leaving scope");
print("inside scope");
};
};

This is useful for cleanup-style logic and for code that should always run at the end of a block or function.

You can also defer from inside loops and labelled scopes.

=> @basic_block {
defer print("basic_block defer");
42;
};

The exact moment a deferred action runs is tied to the scope it belongs to.

Calibre also supports move, which explicitly moves a value. Note that by default values will be copied instead of moved.

let text := "moved value";
print(move text);

move also appears in assignments.

let mut next_cells := [1, 2, 3];
let cells := move next_cells;

Using defer and move makes cleanup intentions clearer in lower-level or more stateful Calibre code. However also keep in mind that the interpreter will try and automatically clean up unused variables at the end of a scope however it is currently very lenient.

Calibre also provides an explicit drop operation for removing a value immediately.

let mut file := try File.open_write("out.txt") : e => panic(e);
file.write_line("hello");
drop file;

defer and drop combine well for cleanup at scope exit:

const main := fn => {
let mut file := try File.open_write("out.txt") : e => panic(e);
defer drop file;
file.write_line("first line");
};