Choose if to test a condition, match to select a case, and for to visit each item. Trace the example to see which task counts toward the remaining time.
Install Topaz using First Program. The Data and Control lesson introduces the records and array used here.
Classify tasks and total the remaining time
Save this code as data-control.tpz in your working folder.
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")In that folder, check the file and run it.
topaz check data-control.tpz
topaz run data-control.tpzThe check succeeds with exit code 0. The program prints these results.
Run first program: done
Build application: focused
remaining: 25 minutesFollow each decision
The loop gives each array element the name task. For the completed task, !task.done is false, so remaining stays 0. The function pace returns "done" before reaching its match.
The second task is unfinished. Its 25 minutes are added to remaining. In pace, 25 matches 16..30, so the result is "focused".
match evaluates task.minutes once and tests arms from top to bottom. Here, each case starts an arm with a pattern and a result. The range patterns test which interval contains the value. _ matches any remaining value, so other integers produce "deep".
| Task | Choose | Result |
|---|---|---|
| Select by a boolean condition | if | The selected branch runs |
| Select by a value or its structure | match | The selected arm supplies its value |
| Process each item in order | for | Each iteration runs the body |
Use if condition { ... } else { ... } when both outcomes need handling. To use an if or match as a value, give its branches compatible result types. A for used as an expression collects body results in an Array. A statement-position for or a while loop performs actions without producing a result value.
Use patterns to test and name values
A pattern can check a value, give it a name, or extract its parts. A literal or range pattern tests the value. A name such as task binds the value without testing its contents.
Some(value) extracts a present value from Option. Err(message) extracts an error from Result. Record patterns extract the fields they name. See Records & Nominal Data for record and enum declarations.
The array pattern [head, ..tail] binds the first item to head and the remaining items to the array tail. _ matches a value without giving it a name.
Use if let pattern = value { ... } to run a block when one pattern matches. Add else if a mismatch needs handling. while let repeats until the pattern fails. The names they bind are immutable and visible inside the successful block.
Correct a pattern
In an array pattern, change [head, ...tail] to [head, ..tail]. Three dots expand arrays in literals or calls. Two dots collect the remaining items in a pattern.
For an enum, create a value with the enum name, as in Status.Paused("review"). In a match arm, use the variant name, as in case Paused(reason) =>.
Match coverage and iteration rules
- Enum matches must handle every declared variant. A guard adds a condition to an arm, so a guarded arm does not establish coverage.
- When static checking cannot establish complete coverage, include an explicit
_arm for the remaining cases. - Patterns evaluate from left to right. Names bound by a failed alternative are unavailable in later alternatives.
- A pattern mismatch in a comprehension causes a runtime fault. Use an
iffilter before a later pattern extracts parts from selected items. - Arrays, integer ranges, sets, and
map.keyshave defined iteration orders. Strings require scalar operations before iteration. - User-defined patterns and iteration, generators, exception handling, and labels on
whileorforare not supported.
Continue to Collections & Comprehensions to choose a collection and filter its values.