Обращайтесь к этой странице, когда значение может отсутствовать или операция может завершиться неудачно. Сначала задайтесь вопросом не «какой оператор короче?», а «может ли вызывающая сторона продолжить работу?».
Выбирайте по смыслу
| Ситуация | Что использовать |
|---|---|
| Отсутствие значения — обычный исход внутри Топаза | Option<T> с Some(value) или None |
| Внешние данные явно содержат nullable-поле | T | null |
| Вызывающая сторона может обработать осмысленную ошибку | Result<T, E> с Ok(value) или Err(error) |
| Программа нарушила контракт времени выполнения | Сбой: вычисление прерывается и не создаёт значение |
Для обычного отсутствия в API Топаза предпочитайте Option. Оставляйте null для данных и границ интеграции, где он действительно присутствует. Используйте Result, когда вызывающей стороне необходима причина ошибки или выбор способа восстановления.
Превратите неверный ввод в восстанавливаемый результат
Эта полная программа преобразует отсутствие, возвращённое toInt, в Result с понятным сообщением:
record УчебнаяЗадача {
название: string,
минуты: int,
}
function разобратьМинуты(текст: string) -> Result<int, string> {
match toInt(текст) {
case Some(значение) if значение > 0 => Ok(значение)
case _ => Err("minutes must be a positive integer")
}
}
function создатьЗадачу(название: string, текстМинут: string) -> Result<УчебнаяЗадача, string> {
let минуты = разобратьМинуты(текстМинут)?
Ok(УчебнаяЗадача { название: название, минуты: минуты })
}
function проверить(текстМинут: string) -> () {
print("input: {текстМинут}")
defer { print("inspection finished") }
match создатьЗадачу("Build application", текстМинут) {
case Ok(задача) => print("ready: {задача.название}, {задача.минуты} minutes")
case Err(сообщение) => print("cannot add task: {сообщение}")
}
}
проверить("25")
проверить("later")Проверьте и запустите программу:
topaz check failures-resources.tpz
topaz run failures-resources.tpzinput: 25
ready: Build application, 25 minutes
inspection finished
input: later
cannot add task: minutes must be a positive integer
inspection finishedtoInt возвращает Option<int>, поскольку у текста, не являющегося целым числом, отсутствует разобранное значение. разобратьМинуты определяет, что это отсутствие существенно для вызывающей стороны, и преобразует его в Err. В создатьЗадачу постфиксный ? извлекает значение из 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 задачи = ["Run first program", "Build application"]
print(задачи[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(задачи[2])
| ^^^^^^^^^
Выход за границы — это сбой. Он прерывает вычисление и не создаёт ни None, ни Err. Постфиксный ?, оператор ??, необязательная цепочка и concurrent не перехватывают и не преобразуют сбои. Некоторые неверные операции с константами проверка отклоняет ещё до запуска.
Точные границы
- Постфиксный
?разрешён только в функции или замыкании, чей возвращаемый тип может нести то же значение ошибки. - Общий
try, исключения, перехват сбоев, ключевые слова panic и автоматические повторы не являются текущими формами Топаза. assert(...)доступна только в явно выбранном кодеtest-profile. Это не инструкция проверки для обычной программы.- Очистку при обычном выходе из области выполняет
defer. Граница очистки при сбое уже, поэтому сбой нельзя считать восстанавливаемымResult.
Продолжите с пошаговым уроком Ошибки и ресурсы, точными правилами Defer и ресурсы и границей сбоев на странице Поведение среды выполнения.