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");};