Error handling
Lake has no exceptions and no null. Fallible operations return a
value that encodes success or failure, and unrecoverable bugs abort
loudly with panic.
§Option — a value or nothing
Option[T] is the standard enum for “maybe a value”:
+std.option.{ Option is_some unwrap_or }
# Option[T] is enum { Some(T) None }Instead of returning a null pointer, a lookup returns Some(v) or
None, and the caller must handle both — checked by when
exhaustiveness:
describe is {
o Option[i64] -> ret buf {
when o {
Some(v) -> { ret "present" }
None -> { ret "absent" }
}
}
}unwrap_or(o d) extracts the value or falls back to d.
§Result — success or failure
Result[T E] carries an error value on the failure path:
+std.result.{ Result is_ok }
# Result[T E] is enum { Ok(T) Err(E) }
handle is {
r Result[i64 buf] -> ret i64 {
when r {
Ok(v) -> { ret v }
Err(e) -> { ret 0 - 1 }
}
}
}Because Ok and Err are variants, the compiler forces you to address
the error case — there is no way to “forget” to check.
§panic — for the unrecoverable
When a bug means the program cannot sensibly continue, panic prints a
message with the call-site location and aborts:
+std.panic.{ panic assert }
main is {
_ -> {
panic("invariant violated")
}
}lake: panicked at src/main.lake:4:5: invariant violated
assert(cond msg) is the everyday guard — it panics with msg unless
cond holds:
pin assert(i < n "index out of range")panic is the Rust-style escape hatch: use Option/Result for
expected failure, panic/assert for “this should never happen”.
§Key ideas
- No exceptions, no null: failure is a value (
Option[T],Result[T E]). whenexhaustiveness forces every case to be handled.panic(msg)aborts with afile:line:collocation;assert(cond msg)guards invariants.