Guide
Modules
Multi-file programs since Sprint 11: import loads a neighbor file, pub fn is the export, and access is always qualified.
/// Doubles a number.
pub fn double(x: Int) -> Int = x * 2
/// Clamps x into [lo, hi].
pub fn clamp(x: Int, lo: Int, hi: Int) -> Int:
if x < lo:
return lo
if x > hi:
return hi
return ximport mathx
fn main() -> Void:
print("{mathx.double(21)}")
let scores = [120, -4, 55]
let clamped = scores.map(fn(s: Int) -> Int = mathx.clamp(s, 0, 100))
print("{clamped}")import mathx finds mathx.pt next to the importing file. pub is the export keyword — for functions, records, and enums alike — and pub already requires a /// doc comment, so a module's API is documented by construction. Private items stay module-internal.
/// A traffic-light color.
pub enum Color:
Red
Rgb(r: Int, g: Int, b: Int)
/// A 2D point.
pub record Point:
x: Int
y: Int
/// Shifts a point horizontally.
pub fn shift(p: Point, dx: Int) -> Point = Point(x: p.x + dx, y: p.y)import shapes
fn describe(c: shapes.Color) -> Text:
match c:
case shapes.Color.Red:
return "red"
case shapes.Color.Rgb(r: r, g: _, b: _):
return "rgb starting {r}"
fn main() -> Void:
let p = shapes.shift(shapes.Point(x: 1, y: 2), 9)
print("{p}")
print(describe(shapes.Color.Rgb(r: 7, g: 8, b: 9)))Since Sprint 12, pub record and pub enum cross the module boundary too: annotate with shapes.Point, construct with shapes.Color.Rgb(r: …), match with case shapes.Color.Red: — exhaustiveness names missing cases in qualified form, and a Point built inside the module equals a shapes.Point built by you.
Imported modules contain declarations only — top-level code runs in the entry file, and ptc test runs the entry file's tests (run a module directly to execute its own). Cycles, self-imports, and missing files are teaching errors; a typo lists the module's available functions.