Topaz разделяет отсутствие, восстанавливаемую ошибку и прерывающий fault, чтобы программа и бэкенды одинаково понимали доступный путь управления.
Политика
Option<T> — канонический контейнер отсутствия; T | null предназначен для nullable data boundaries. ?? снимает ровно один слой Option/null и вычисляет fallback только при пустоте. ?. вычисляет receiver один раз, short-circuit аргументы, сохраняет модель Option/null и уплощает один optional-слой member. Instruction-only ??= присваивает только при пустоте и не оборачивает Some. Восстанавливаемая ошибка использует Result<T,E>, Ok, Err и постфиксный ?.
Определённое поведение
expr? снимает Ok или немедленно возвращает тот же Err из совместимой функции/лямбды. Fault не является значением: bounds failure, целочисленное деление на ноль, динамический нулевой step, overflow, отрицательная степень и runtime match miss прерывают вычисление. ?, ??, optional chaining и concurrent не ловят fault. Безопасные чтения коллекций возвращают Option.
Ограничения и явный отказ
?. недопустим для обычной non-null записи. Отклоняются ??= у nonoptional target, raw T в Option<T> ??=, ? вне совместимого Result-callable, случайный Err(Err(...)), синтаксис try, panic keyword и обычный public assert. Union, смешивающий Option и null, неканоничен до явного match.
Отложенная граница
Fault catching, exceptions, общий try, stack recovery, conversion отмены, автоматический retry и широкие assertion frameworks отложены. Host cleanup после fault возможен как runtime policy, но язык не обещает Result-преобразование или выполнение всех lexical defer.
Пример
function parsePort(text: string) -> Result<int, string> {
match toInt(text) {
case Some(port) => Ok(port)
case None => Err("port must be an integer")
}
}
function start(text: string) -> Result<string, string> {
let port = parsePort(text)?
return Ok("listening on {port}")
}