Guide
Pattern matching
match/case destructures values — and the compiler proves your match is exhaustive before it ever runs.
fn label(n: Int) -> Text:
match n:
case 0:
return "zero"
case 1:
return "one"
case other:
return "many ({other})"
fn main() -> Void:
print(label(0))
print(label(7))$ ptc run match.pt
Recorded output of the real compiler
Patterns: literals, the wildcard _, bindings, Some/None/Ok/Err, record patterns with all fields, and qualified enum variants. A match on an Option must cover Some and None; a match on an enum must cover every variant — or end with an irrefutable arm.
fn size_class(n: Int) -> Text:
match n:
case v if v > 100:
return "large"
case v if v > 10:
return "medium"
case v:
return "small ({v})"
fn main() -> Void:
print(size_class(500))
print(size_class(50))
print(size_class(5))$ ptc run guards.pt
Recorded output of the real compiler
Guards (since Sprint 22): a pattern may carry an if condition, checked after the pattern matches with its bindings in scope. The guard must be Bool — no truthiness — and a false guard falls through to the next arm. Guarded arms never count toward exhaustiveness, so the checker still demands an unguarded arm for every case.