Обращайтесь к этой странице, когда значение может отсутствовать или операция может завершиться неудачно. Сначала спросите не «какой оператор короче?», а «может ли вызывающая сторона продолжить работу?».
Выбирайте по смыслу
| Ситуация | Что использовать |
|---|---|
| Отсутствие значения — обычный исход внутри Топаза | Option<T> с Some(value) или None |
| Внешние данные явно содержат nullable-поле | T | null |
| Вызывающая сторона может обработать осмысленную ошибку | Result<T, E> с Ok(value) или Err(error) |
| Программа нарушила контракт времени выполнения | Сбой (fault): вычисление прерывается и не создаёт значение |
Для обычного отсутствия в API Топаза предпочитайте Option. Оставляйте null
для данных и границ интеграции, где он действительно присутствует. Используйте
Result, когда вызывающей стороне нужны причина ошибки или выбор способа
восстановления.
Превратите неверный ввод в восстанавливаемый результат
Эта полная программа превращает отсутствие, возвращённое toInt, в
Result с понятным сообщением:
record StudyTask {
title: string,
minutes: int,
}
function parseMinutes(text: string) -> Result<int, string> {
match toInt(text) {
case Some(value) if value > 0 => Ok(value)
case _ => Err("minutes must be a positive integer")
}
}
function makeTask(title: string, minuteText: string) -> Result<StudyTask, string> {
let minutes = parseMinutes(minuteText)?
Ok(StudyTask { title: title, minutes: minutes })
}
function inspect(minuteText: string) -> () {
print("input: {minuteText}")
defer { print("inspection finished") }
match makeTask("Build application", minuteText) {
case Ok(task) => print("ready: {task.title}, {task.minutes} minutes")
case Err(message) => print("cannot add task: {message}")
}
}
inspect("25")
inspect("later")Проверьте и запустите программу:
topaz check failures-resources.tpz
topaz run failures-resources.tpz
input: 25
ready: Build application, 25 minutes
inspection finished
input: later
cannot add task: minutes must be a positive integer
inspection finishedtoInt возвращает Option<int>, потому что у текста, который не является
целым числом, нет разобранного значения. parseMinutes решает, что это
отсутствие важно вызывающей стороне, и превращает его в Err. В makeTask
постфиксный ? извлекает значение из Ok, а при Err немедленно возвращает
ошибку из совместимой функции с результатом Result. Последний match явно
обрабатывает оба исхода.
Работайте с необязательными и nullable-значениями
Необязательный доступ и значение по умолчанию сохраняют различие моделей:
- Если
maybeUser: Option<{ name: string }>, то результатmaybeUser?.nameтакже остаётсяOption, аmaybeUser?.name ?? "guest"даётstring. - Если
configPath: string | null, выражениеconfigPath ?? "default.toml"использует запасное значение только приnull. target ??= value— инструкция, которая присваивает значение только пустой цели. Для целиOption<int>требуетсяSome(42), а не просто42: Топаз не добавляетSomeавтоматически.
Операторы ?. и ?? вычисляют левую часть ровно один раз. ?. также не
вычисляет аргументы метода, если получатель пуст. Каждый оператор снимает или
уплощает один необязательный слой и не превращает Option в null.
Исправление частой ошибки: для значения, которое не является
необязательным или nullable, используйте обычную точку .. Если тип сочетает
Option<T> и null, явно разберите случаи через match, а не наслаивайте
сокращения.
Сбой не является значением ошибки
Эта программа обращается к несуществующему элементу массива:
let tasks = ["Run first program", "Build application"]
print(tasks[2])Команда topaz run intentional-fault.tpz завершается с ненулевым кодом:
error[TPZ4001]: index 2 is out of bounds for an array of length 2
--> intentional-fault.tpz:2:7
|
2 | print(tasks[2])
| ^^^^^^^^
Выход за границы — это сбой (fault): он прерывает вычисление и не создаёт ни
None, ни Err. Постфиксный ?, оператор ??, необязательная цепочка и
concurrent не перехватывают и не преобразуют сбои. Некоторые неверные
операции с константами проверка отклоняет ещё до запуска.
Точные границы
- Постфиксный
?разрешён только в функции или замыкании, чей возвращаемый тип может нести то же значение ошибки. - Общий
try, исключения, перехват сбоев, ключевые слова panic и автоматические повторы не являются текущими формами Топаза. assert(...)доступна только в явно выбранном кодеtest-profile; это не инструкция проверки для обычной программы.- Очистку при обычном выходе из области выполняет
defer. Граница очистки при сбое уже, поэтому сбой нельзя считать восстанавливаемымResult.
Продолжите с пошаговым уроком Ошибки и ресурсы, точными правилами Defer и ресурсы и границей сбоев на странице Поведение среды выполнения.