История вопроса
Оператор match в Rust — это мощный инструмент сопоставления с образцом, заимствованный из функциональных языков. В отличие от аналогов в C/C++, в Rust осуществляется строгая проверка полноты (exhaustiveness checking), и на каждый возможный вариант должны быть варианты ветки.
Проблема
Ошибки при работе с match чаще всего связаны с неправильным учётом всех вариантов типа (например, enum), неверной работой с guard'ами (условиями на ветки) или сложной вложенной структурой. Неправильная обработка приводит к ошибкам на этапе компиляции или к неявно неверной логике.
Решение
_).if после паттерна).Пример кода:
enum Shape { Circle(f64), Rectangle { width: f64, height: f64 }, } fn print_area(s: Shape) { match s { Shape::Circle(r) if r > 0.0 => println!("area = {}", 3.14 * r * r), Shape::Rectangle { width, height } if width > 0.0 && height > 0.0 => println!("area = {}", width * height), _ => println!("invalid shape"), } }
Ключевые особенности:
Влияет ли порядок веток в match на выполнение?
Да, порядок веток важен: как только найдено первое совпадение, последующие не проверяются. Это особенно критично с pattern guard — если раньше стоит ветка с guard, она перехватит значение до catch-all.
Обязателен ли catch-all (_) при match по enum?
Нет, если вы явно перебрали все случаи (и сами варианты объявления типа не поменяются со временем). Однако catch-all нужен при работе с типами, у которых могут появиться дополнительные значения или когда не хочется обработать все ветки явно.
Можно ли в одной ветке match использовать несколько паттернов (alternatives)?
Да. Через вертикальную черту (|) можно объединять паттерны:
match x { 1 | 2 | 3 => println!("one, two or three"), _ => println!("something else"), }
_ слишком рано (до специфичных веток)Разработчик написал match с catch-all в начале и не смог корректно обработать специфические случаи.
Плюсы:
Программа компилируется.
Минусы:
Специфичная логика не работает никогда, часть кода не покрывается.
Явная обработка всех вариантов enum, catch-all — только последней веткой, отдельные guard'ы для нетиповых случаев.
Плюсы:
Предсказуемость, компилятор помогает не забыть вариант, легко расширять типы.
Минусы:
Дополнительный шаблонный код при большом количестве вариантов.