Defer allows us to specify a function to execute once the current function being executed returns. The order in which defers occur in reverse order in which they are declared. This also gives us a nice way to perform cleanup tasks.
use fmt;
fn cleanup(data: []u8) void = {
fmt::println("Do the cleanup work if something bad happens")!;
free(data);
};
export fn main() void = {
// As the line states this function is defined first, but will
// be the last to execute in the defer chain.
defer fmt::println("Defined first, but called last")!;
fmt::println("Doing some more work here")!;
// We define anothe defer here that will be called before the
// defer above.
defer fmt::println("Defined second, but called second to last")!;
// We can use defer as a cleanup pattern in case something goes
// wrong during processing. We can allocate some memory of data.
const data: []u8 = alloc([], 10z)!;
// We'll set a local boolean to keep track if this are ok or
// not. Immediately after that we define a defer with an if to
// check if ok's value changed. If it changed to false then the
// cleanup function runs as part of the defer chain.
let ok = true;
defer if (!ok) cleanup(data);
// Further down we can perform some logic that might cause ok's
// value to change to false. This could also be when we try to
// write data to a file and we match on an error and we set
// ok's value to false to ensure cleanup runs.
if (len(data) < 100z) {
ok = false;
};
fmt::println("We're all done")!;
};
$ hare run defer.ha
4/4 tasks completed (100%)
Doing some more work here
We're all done
Do the cleanup work if something bad happens
Defined second, but called second to last
Defined first, but called last
Back to table of contents