Error Handling
ZZ has no exceptions. Fallible operations return Option or Result
variants, and the compiler helps you handle every case.
Option: a value or nothing
Section titled “Option: a value or nothing”Parsing, lookups and decodes return Option:
count := input("How many users? ") |> int() ?? 1?? unwraps .some(v) to v and substitutes the fallback for .none.
Match when you need to branch instead:
match env.get_var("HOME") { .some(home) => println("Home: {home}"), .none => println("HOME not set"),}Result: success or context
Section titled “Result: success or context”Filesystem, network and JSON operations return Result:
import std.fs
match fs.read_file("data.txt") { .ok(content) => println(content), .err(e) => println("Error: {e}"),}Unwrap with intent
Section titled “Unwrap with intent”Three methods document how much you care:
x := .some(42)x.unwrap() // 42 — panics on .none, use when impossiblex.unwrap_or(0) // 42 — the common defaultx.expect("missing") // 42 — panics with YOUR message
y: Option<int> = .noney.unwrap_or(0) // 0Prefer unwrap_or and ?? in normal code; reserve unwrap for invariants
and expect for messages a future debugger will thank you for.
Exhaustive match
Section titled “Exhaustive match”The compiler wants every case covered — _ is your catch-all:
match status { .ok(data) => render(data), .err(e) => log(e),}An uncovered value is a compile error, not a runtime surprise.
Diagnostics that teach
Section titled “Diagnostics that teach”Typos get Levenshtein suggestions instead of a shrug:
error: undefined variable `printn` = did you mean `println`?
error: struct `Point` has no field `xz` = did you mean field `x`?Warnings catch dead weight — unused imports and variables:
warning: unused import `pkg`warning: unused variable `unused_var`Every error carries a code, a span and a fix hint:
error[E001]: type mismatch --> src/main.zz:5:12 | 5 | x: int = "hello" | ---- ^^^^^^^^ expected int, found str | = help: cast string to int with `int()` functionFix at machine speed
Section titled “Fix at machine speed”zz check src/ # report everythingzz fix src/ # apply safe auto-fixeszz fix --hard # apply ambiguous fixes too, no promptsA typical auto-fix renames to suppress a warning:
warning[W001]: unused variable --> src/main.zz:3:5 | 3 | x := 42 | ^^^^^^^ | = help: prefix with `_` to suppress: `_x := 42` = fix: `_x := 42`