Pattern matching в Rust позволяет разбивать значения по структуре, анализировать и обрабатывать сложные типы с помощью конструкций match, if let, while let. Деструктуризация (разложение на части) удобна для работы с кортежами, структурами, enum'ами и даже ссылками.
Пример с enum:
enum Message { Quit, ChangeColor(i32, i32, i32), Write(String), } let m = Message::ChangeColor(255, 0, 0); match m { Message::Quit => println!("Quit!"), Message::ChangeColor(r, g, b) => println!("Color: {} {} {}", r, g, b), Message::Write(text) => println!("Text: {}", text), }
Деструктуризация структур:
struct Point { x: i32, y: i32 } let p = Point { x: 10, y: 20 }; let Point { x, y } = p;
Тонкости:
ref и ref mut позволяет получить ссылки при разложении.@ можно "переименовать" часть паттерна.if guard).&SomeType) — важно помнить о владении и borrowing.Можно ли всегда использовать "_" (подчеркивание) чтобы игнорировать части паттерна и избежать предупреждений компилятора?
Не всегда. Подчеркивание действительно пропускает значение, но если не обрабатывать все варианты enum'а и использовать "_" для catch-all, вы можете упустить обработку новых вариантов при расширении enum в будущем. Лучше всегда явно перечислять важные варианты, чтобы компилятор предупредил о нерассмотренных случаях!
match result { Ok(val) => ..., Err(err) => ..., //_ => ... // не рекомендуется для enum! }
История
В приложении IoT устройство перестало отвечать из-за того, что при добавлении нового варианта enum в месте pattern matching использовался catch-all "_". Ошибка осталась невидимой до деплоя. После этого критичные enum'ы всегда разбирались только с явным перебором вариантов.
История
Для сложной структуры с вложенными кортежами забыли добавить синтаксис деструктуризации рекурсивных полей, и вместо получения ссылок коды случайно клонировали большие объекты, что привело к снижению производительности.
История
В одном функционале передачи сообщений между потоками использовали деструктуризацию через if-let, но игнорировали редкие варианты enum. При появлении новой бизнес-логики сообщения просто терялись. После этого в командном стиле было заведено правило — каждое match выражение должно быть исчерпывающим без catch-all.