Enums
Перечисления
Перечисление — это тип данных, который позволяет определить набор именованных значений (вариантов). Каждый вариант может быть просто именем или содержать дополнительные данные.
Здесь мы определили перечисление Money с двумя вариантами: Rub, и Kop. Эти варианты не содержат дополнительных данных — они просто имена, которые представляют возможные состояния. В терминах Rust такие варианты без данных часто называют “unit-like” (похожими на Unit), но это не совсем то же самое, что массив или указатели.
Unit
“Unit” в Rust — это специальный тип (), который имеет только одно значение, тоже обозначаемое как (). Это что-то вроде “пустого значения”, которое часто используется, когда функция ничего не возвращает. Например:
В случае с Money каждый вариант (Rub и Kop) сам по себе не является типом (), но его можно рассматривать как “unit-like”, потому что он не несёт дополнительных данных. Это просто маркер, который говорит: “Я одно из двух состояний”.
Enum в памяти
Внутри памяти Money представлен как небольшое целое число (обычно 1 байт для простых перечислений вроде этого), называемое “дискриминантом”. Этот дискриминант указывает, какой вариант сейчас используется:
Money::Rub→ 0Money::Kop→ 1 Но это внутренняя реализация. Для программиста это просто разные состояния.
match
Аналог switch в других языках, однако, круче: его проверка не сводится к bool, а также реакция на каждое действие может быть блоком:
n - привязка (binding). Когда ты пишешь n if n > 0, то говоришь: “возьми значение number и назови его n для этой ветки. Затем проверь условие if n > 0. Если оно истинно, выполни действие”. Обычно match используется с точными значениями (например, 1 => ..., 2 => ...), но добавление if позволяет проверять более сложные условия, как в этом примере (положительное, отрицательное или ноль). Это называется guards (охрана) в Rust.
Ещё пример:
match как выражение
Проверка условия и запуск соответствующего метода:
Использование Option как enum
if let
В случае, когда выбор сводится к тому, что мы сравниваем 1 вариант с заданным паттерном и далее запускаем код при успехе, а в случае неравенства ничего не делаем, можно вместо match применять более короткую конструкцию if-let:
Превращается в:
Применение if-let - это синтаксический сахар, укорачивает код, однако, лишает нас проверки наличия обработчиков на все варианты возвращаемых значений как в конструкции match.
Сравнение величин
Для сравнения значений в переменных есть метод std::cmp, который возвращает объект типа enum Ordering с вариантами: