← На главную

Почему option-типы оказались сложнее, чем кажутся

02.11.2026 20:08 · hackernews

Автор языка Copper описал опыт добавления union- и option-типов. Union позволяет значению принадлежать одному из нескольких типов, например Int или String, но перед специфичными операциями фактический вариант нужно различить через match. В Copper общий union требовал тега, а сочетание Pointer|Nothing оптимизировалось через NULL.

Ради простой компиляции пришлось запретить вложенные union, сделать порядок типов значимым и объявить несовместимыми наборы с разным числом вариантов. Это упростило назначение тегов и позволило добавить сокращение для раннего возврата ошибки, но реализация всё равно оказалась слишком сложной для минималистичного низкоуровневого языка. Поэтому автор сосредоточился на частном случае T|Nothing, обозначаемом T?.

Для nil предлагается резервировать одно значение исходного типа: нулевой адрес для указателя, -1 для знакового индекса или неиспользуемый код для 24-битного цвета. Такой подход не требует дополнительного тега и хорошо согласуется с C API. Однако подходящее значение существует не у каждого типа, а вложенный T?? представить нельзя.

Первый вариант уточнения типа использует конструкцию as: если значение не nil, оно копируется в неизменяемую локальную переменную типа T. Она доступна внутри if и while или справа от and. Конструкция or else позволяет сразу выйти из функции или цикла и избежать глубокой вложенности проверок. Для заведомо безопасных исключений есть notNil с проверкой в отладочной сборке, а defopt разрешает определять методы для самого option-типа.

Затем автор попробовал автоматический nil-checker в духе TypeScript и Kotlin: компилятор выводил отсутствие nil из условий и ранних return. Чтение кода стало проще, но циклы потребовали двухпроходного анализа, обобщённые функции не получали уточнённый тип, а корректность программы начала зависеть от неочевидных возможностей анализатора. Компилятор также стал примерно на 5% медленнее, поэтому от этого варианта отказались.

Перенос компилятора и текстового редактора Clade выявил несколько потенциальных и реальных ошибок. Сложнее оказался экспериментальный декомпилятор, где алгоритмы полагаются на инварианты, недоступные компилятору. Автор признаёт пользу option-типов: они явно документируют возможность nil и предотвращают случайные разыменования. Но окончательный выбор для него — баланс между этой защитой и желанием сохранить язык простым, а компилятор — помощником, который не заставляет переписывать понятные алгоритмы.

Читать оригинал →