Skip to content

Advanced Features

Methods attach to structs with self first:

struct Rectangle {width: int, height: int}
impl Rectangle {
func area(self) -> int {
return self.width * self.height
}
func perimeter(self) -> int {
return (self.width + self.height) * 2
}
}
rect := Rectangle{width: 3, height: 4}
println(rect.area()) // 12
println(rect.perimeter()) // 14
func min<T: Ord>(a: T, b: T) -> T {
if a < b { a } else { b }
}
println(min(3, 5)) // 3

Bounds like Ord unlock comparisons; inference fills the parameters at each call site. See Language Reference for the full rules.

Option and Result compose with match, ?? and the unwrap_* family instead of branching on nulls:

func find_name(id: int) -> Option<str> {
if id == 1 {
.some("Ada")
} else {
.none
}
}
match find_name(1) {
.some(name) => println("Found: {name}"),
.none => println("Unknown id"),
}
mult := 3
scaled := map(range(1, 6), |x: int| x * mult)
println(scaled) // [3, 6, 9, 12, 15]

zz run type-checks and executes through the VM — ideal for iteration. zz build emits a native binary instead:

Terminal window
zz build app.zz # dev binary next to the source
zz build -p app.zz # optimized release binary
zz build --static app.zz # static binary
zz build --pgo app.zz # profile-guided build

Both runtimes share the pure-ZZ standard library, so library code behaves identically either way.

Imports resolve relative to the source file; std.* loads the built-ins:

import std.math
import std.json
import utils.helper
project/
├── main.zz
└── utils/
└── helper.zz