Skip to content

defer

defer schedules a block to run when the current scope ends — no matter which path it exits by. Multiple defers run in LIFO order (the last scheduled runs first), which is perfect for undoing setup in reverse order:

Cleanup happens on scope exit, in reverse order of scheduling.

19-defer.zolo
Playground
// Feature: `defer` — cleanup on scope exit (LIFO)
// Syntax: `defer expr` or `defer { ... }`
// When to use: ensure resources are released
// (close file, drop lock, restore state) even if
// the function returns early or panics.
// Execution order: LIFO — the last `defer` declared
// runs first.

fn process_file() {
  print("opening file")
  defer print("closing file")  // runs last
  defer print("flushing")  // runs second-to-last

  print("processing")
  print("done")
}

process_file()

// expected:
// opening file
// processing
// done
// flushing
// closing file

// Deferred cleanup combined with early return.
// SKIP: `defer` combined with an explicit `return <value>` from a
// typed function currently fails to lower (the runtime needs to wrap
// the body in `pcall` for defer-on-panic; this conflicts with early
// return). The pattern below uses a void function instead.
fn safe_op(ok: bool) {
  print("start")
  defer print("cleanup guaranteed")

  if !ok {
    print("error -- returning early")
    return
  }
  print("success")
}

print("--- ok call ---")
safe_op(true)
print("--- failed call ---")
safe_op(false)
enespt-br