Functions are first-class citizens in Zith. The language supports multiple function kinds, implicit returns, and closures.
fn add(a: i32, b: i32): i32 { a + b } // explicit type, implicit return
fn add(a: i32, b: i32) { a + b } // inferred return type
// Bound-check: if ok, return normally; if not, propagate as null
fn first<T>(slice: []T): ?T {
slice[0]?
}
ℹ Note: The compiler cannot infer a union return type without an explicit union type hint.
| Kind | Description |
|---|---|
fn |
Standard runtime function. |
const fn |
Resolved at compile time. Must be called inside a const block. |
async fn |
Coroutine (default async). Can yield. |
async<Generator> fn |
Explicit generator — yields a typed sequence. |
flow fn |
Enables marker/dock/jump control flow. Can be noreturn. |
raw fn |
Always unchecked — bypasses safety in both debug and release. |
⚠ Function kinds are orthogonal and cannot be mixed.
Macro calls use the @ prefix — @println, @log, @serialize.
Function calls use bare names — console.write, process, save.
async fn & yield// Default coroutine
async fn fetch(url: string): Response! {
yield;
get_response()!
}
// Explicit generator
async<Generator> fn range(start: i32, end: i32): ?i32 {
for (i in start..end) {
yield i;
i += 1;
}
}
for (v in range(0, 10)) { @println(v); }
A closure is a pack with callable semantics. Capture modes:
let addBase = |base| (n: i32): i32 { base + n };
let f1 = |view x| (n: i32) { x + n };
let f2 = |x| (n: i32) { x += n; };
static vs dynBy default a closure generates an inline (static) call. The dyn qualifier makes it an indirect call via function pointer.
let closure: dyn = |base| { ... };
// Extract / inject the pack at compile time
let pack = @pack closure;
@pack closure = pack;
| Level | Syntax | Semantics |
|---|---|---|
| Full static | let f = \|x\| x + 1; |
Zero overhead. |
| Semi-dynamic | let f: dyn = \|x\| x + 1; |
Function pointer; capture signature statically known. |
| Dynamic pack, static fn | let f: \|opaque\| = \|x\| x + 1; |
Capture pack opaque, no type info inside. |
| Full dynamic | let f: dyn \|opaque\| = \|x\| x + 1; |
Both function and capture opaque; full fat pointer. |
See also: Spec: Functions
Next: Control Flow