Используйте if, когда нужно проверить одно условие, match — когда результат зависит от формы или категории значения, а for — когда действие повторяется для каждого элемента. Шаблоны внутри match и for одновременно проверяют данные и дают имена нужным частям.
Запустите пример
Сохраните код в файле 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")Сначала проверьте программу, затем выполните её:
topaz check data-control.tpz
topaz run data-control.tpz
Строки появятся в порядке элементов массива:
Run first program: done
Build application: focused
remaining: 25 minutesПроследите за тремя решениями
Цикл связывает очередной элемент массива с именем task. Вложенный if отвечает на один вопрос: задача ещё не выполнена? Здесь не требуется ни разбирать значение на части, ни выбирать из нескольких категорий.
Когда важны оба исхода, пишите if condition { ... } else { ... }.
Если ветви возвращают совместимые значения, весь if тоже является значением.
В функции pace первый if отдельно обрабатывает выполненную задачу. Затем match вычисляет task.minutes один раз и проверяет ветки case сверху вниз. 1..15 и 16..30 — шаблоны диапазонов. _ принимает все остальные целые числа, поэтому результат определён для любого входа.
| Форма | Когда выбирать | Результат |
|---|---|---|
if | Выбор зависит от одного логического условия | Значение при совместимых результатах ветвей либо только действие |
match | У значения есть несколько значимых форм или категорий | Значение выбранной ветви и доступные в ней связанные имена |
for | Нужно посетить каждый элемент в установленном порядке | Действия в позиции инструкции либо Array результатов в позиции выражения |
Шаблон проверяет и связывает
Литеральный шаблон и шаблон диапазона проверяют значение. Имя вроде task связывается с совпавшим значением. Шаблоны конструкторов Some(value) и Err(message) извлекают содержимое Option и Result. Шаблон записи выбирает поля по именам.
В шаблоне массива остаток обозначается .., а не .... Форма case [head, ..tail] => связывает первый элемент с head, а остальные — с tail типа Array. Если оставшееся значение не нужно, используйте _.
Форма if let pattern = value { ... } удобна, когда важен один успешный вариант и, возможно, запасная ветвь. while let повторяет ту же проверку до первого несовпадения. Созданные ими имена неизменяемы и видны только в успешном блоке.
Частая ошибка
Не пишите [head, ...tail] в шаблоне. ... раскрывает массив в литерале или аргументы при вызове. Каноническая запись остатка списка — [head, ..tail].
Создание и разбор перечисления тоже записываются по-разному. Значение создают с именем перечисления, например Status.Paused("review"), а в шаблоне оставляют только вариант: case Paused(reason) =>.
Точные правила, влияющие на выбор
- Ветви
ifилиmatch, используемых как значение, должны давать совместимые результаты. - Для закрытого перечисления проверяется полнота вариантов. Ветка с дополнительным условием не засчитывается как полное покрытие варианта.
- Если проверяющий не может доказать полноту
match, добавьте явную ветвь_. - Части шаблона проверяются слева направо. Имена из неудачной альтернативы не переходят в следующую.
- Несовпадение допускающего отказ шаблона во включении коллекции вызывает ошибку, а не пропускает элемент. Для фильтрации добавьте явное условие
if. - Порядок обхода определён для
Array, целочисленных диапазонов,Setиmap.keys. Строки напрямую не обходятся. whileиforв позиции инструкции не дают значения.forв позиции выражения собирает результаты тела в исходном порядке.
Пользовательские шаблоны и итераторы, генераторы, перехват ошибок выполнения и метки на while или for в текущий язык не входят.
Начните с примера курса Данные и управление. Формы данных подробно разобраны в разделе Записи и номинальные данные, а порядок обхода и фильтрация — в разделе Коллекции и включения.