Use if for one yes-or-no condition, match when the shape or category of a value chooses the result, and for when the same work should happen for each item. Patterns are the forms inside match and for that both test data and give names to the parts you need.
Run one example
Save this as data-control.tpz:
record StudyTask {
title: string,
minutes: int,
done: bool = false,
}
function pace(task: StudyTask) -> string {
if task.done {
return "done"
}
match task.minutes {
case 1..15 => "quick"
case 16..30 => "focused"
case _ => "deep"
}
}
let tasks: Array<StudyTask> = [
StudyTask { title: "Run first program", minutes: 10, done: true },
StudyTask { title: "Build application", minutes: 25 },
]
let mut remaining = 0
for task in tasks {
if !task.done {
remaining = remaining + task.minutes
}
print("{task.title}: {pace(task)}")
}
print("remaining: {remaining} minutes")Check it before running it:
topaz check data-control.tpz
topaz run data-control.tpz
The result follows the array order:
Run first program: done
Build application: focused
remaining: 25 minutesFollow the decisions
The loop binds each array element to task. The inner if asks one boolean question: is this task unfinished? It neither needs to classify several cases nor take the value apart.
When both outcomes matter, write if condition { ... } else { ... }.
Compatible branch values make the whole if a value.
pace first uses if for the exceptional completed case. Its match then evaluates task.minutes once and tries the case arms from top to bottom. 1..15 and 16..30 are range patterns. _ is the catch-all, so every other integer has a result.
| Choose | When it fits | What it produces |
|---|---|---|
if | One condition decides between branches | A value when compatible branches produce values; otherwise an effect-only statement |
match | A value has several meaningful shapes or categories | The selected arm’s value, with any pattern bindings in that arm |
for | Every item should be visited in iteration order | Effects as a statement, or an Array of body results in expression position |
Patterns select and bind
A literal or range pattern tests a value. A name such as task binds the matched value. Constructor patterns such as Some(value) and Err(message) open Option and Result values. Record patterns select named fields.
Array patterns use .., not call spread syntax. case [head, ..tail] => binds the first element and gives the remaining elements to tail as an Array. Use _ when you need a fallback but do not need the value.
if let pattern = value { ... } is useful for one success shape and an optional fallback. while let repeats the same test until it no longer matches. Their bindings are immutable and exist only inside the successful body.
Common mistake
Do not write [head, ...tail] in a pattern. ... is used for array and call spread; the canonical list-rest pattern is [head, ..tail].
Enum construction and enum matching also look deliberately different. Construct with the enum name, such as Status.Paused("review"), but match the variant without qualification: case Paused(reason) =>.
Exact behavior that affects a choice
- A value-producing
iformatchneeds compatible branch results. - A closed enum match is checked for complete variant coverage. A guarded arm does not count toward that coverage.
- When the checker cannot prove a match complete, use an explicit
_arm. - Patterns test from left to right. Bindings from a failed alternative do not leak into the next one.
- A refutable pattern that fails in a collection comprehension is an error, not a filter. Add an explicit comprehension
ifclause to skip items. Array, integer ranges,Set, andmap.keyshave defined iteration order. Strings are not directly iterable.whileand statement-positionforare valueless. Aforused as an expression collects its body results in source order.
User-defined patterns, generators, general user-defined iteration, fault-catching control forms, and labels on while or for are not part of the current language.
Continue from the course example in Data and Control. See Records & Nominal Data for the shapes patterns can open and Collections & Comprehensions for iteration and filtering.