Опциональные типы вместо null
На почте есть ячейка «посылка пришла». Она либо содержит номер, либо пуста. Номер 0 нельзя без договора считать пустотой: вдруг это настоящий номер. Лучше иметь отдельную отметку наличия. Опциональный тип делает эту отметку частью значения.
Мы ищем первый положительный результат в списке. Иногда он есть, иногда нет. Функция должна честно сообщать обе возможности и не заставлять вызывающего угадывать значение-заглушку.
Одна мысль урока
?T отличает отсутствие значения от любого допустимого значения T.
Опора из прошлого урока: Указатели и срезы.
От картинки к записи
Опциональный тип
записывается ?T. Например, ?u16 содержит число либо null. Это не любое число с особой
договорённостью про ноль. Если ноль входит в предметную область, он остаётся полноценным значением.
Отсутствие живёт рядом как отдельная возможность.
Чтобы воспользоваться содержимым, нужно раскрыть опционал. Запись if (result) |value| выполняет ветку, только если значение есть, и даёт ему локальное имя value. Внутри ветки тип уже u16, без вопросительного знака. В ветке else значения нет, поэтому читать его нечего.
Оператор orelse выбирает запасное значение: result orelse 10. Он полезен, когда отсутствие действительно означает допустимое значение по умолчанию. Если отсутствие важно для решения, не прячь его за произвольной десяткой. Сначала реши, что должен узнать пользователь, затем выбирай краткую запись.
Запись result.? раскрывает опционал, утверждая наличие. В безопасных режимах null приведёт к остановке, а не к автоматическому нулю. Эта запись подходит, когда наличие уже доказано логикой, но новичку обычно проще явный if. Не используй принудительное раскрытие, чтобы избавиться от неудобного типа.
Отсутствие и ошибка различаются. Поиск по пустому списку может успешно завершиться без находки. Ошибка была бы другой ситуацией, например невозможностью прочитать сам источник. Если один тип пытается закодировать обе причины одинаковым null, вызывающий теряет информацию. Сегодня у функции только одна причина отсутствия: подходящего элемента нет.
Обычные указатели Zig не допускают нулевой адрес как корректное значение. Поэтому адрес, который может отсутствовать, описывают ?*T, а не *T. Отсутствие видно ещё до чтения памяти. Это не отменяет условия о сроке жизни: ненулевой адрес тоже может стать недействительным после освобождения.
Проверяй два пути. В примере .{} обозначает пустую последовательность, и функция возвращает null. В списке с положительным числом возвращает значение и прекращает поиск. Наличие нуля в начале не должно мешать поиску следующего положительного числа. Это отдельный граничный пример, который лучше назвать явно.
премиум-урок
Продолжение в премиуме: 1 200 ₽ в месяц или 10 000 ₽ в год. Вместе с ним серверные проверки задач и школьные токены AI-коуча.
Оплата пока не подключена: премиум и курсы открываются промокодом.