Привязка образца @
В языке Rust оператор
@называется "bind operator" (оператор привязки) и используется для создания привязки значения к переменной внутри паттерн-матчинга.
Основная концепция
Оператор @ позволяет:
- Проверить, соответствует ли значение паттерну
- Одновременно привязать это значение к переменной
Синтаксис
#![allow(unused)] fn main() { переменная @ паттерн }
Примеры использования
1. Привязка в диапазонах
fn check_number(n: u32) { match n { x @ 0..=9 => println!("Одна цифра: {}", x), x @ 10..=99 => println!("Две цифры: {}", x), x @ 100..=999 => println!("Три цифры: {}", x), _ => println!("Большое число"), } } fn main() { check_number(5); // Одна цифра: 5 check_number(42); // Две цифры: 42 check_number(123); // Три цифры: 123 }
2. Работа с перечислениями (enum)
#![allow(unused)] fn main() { enum Message { Text(String), Number(i32), Coordinate { x: i32, y: i32 }, } fn process_message(msg: Message) { match msg { Message::Text(text) @ Message::Text(_) => { println!("Текстовое сообщение: {}", text) }, Message::Number(n @ 0..=100) => { println!("Число в диапазоне 0-100: {}", n) }, Message::Coordinate { x, y } @ Message::Coordinate { x: 0..=10, y: 0..=10 } => { println!("Координата в квадрате 10x10: ({}, {})", x, y) }, _ => println!("Другое сообщение"), } } }
3. Сложные паттерны с условиями
#![allow(unused)] fn main() { fn process_value(val: Option<i32>) { match val { Some(x @ 1..=10) if x % 2 == 0 => { println!("Четное число от 1 до 10: {}", x) }, Some(x @ 1..=10) => { println!("Нечетное число от 1 до 10: {}", x) }, Some(x) => { println!("Другое число: {}", x) }, None => println!("Нет значения"), } } }
4. Работа со структурами
#![allow(unused)] fn main() { struct Point { x: i32, y: i32, } fn check_point(p: Point) { match p { point @ Point { x: 0..=5, y: 0..=5 } => { println!("Точка в квадрате 5x5: ({}, {})", point.x, point.y) }, Point { x, y } => { println!("Точка вне квадрата: ({}, {})", x, y) }, } } }
5. Вложенные паттерны
#![allow(unused)] fn main() { fn process_nested(value: Option<Option<i32>>) { match value { Some(inner @ Some(1..=10)) => { println!("Внутреннее значение: {:?}", inner) }, Some(Some(x)) => { println!("Другое значение: {}", x) }, Some(None) => println!("Внутренний None"), None => println!("Внешний None"), } } }
Преимущества использования @
- Избегание повторного вычисления - значение вычисляется только один раз
- Улучшенная читаемость - ясное указание на то, что значение используется в нескольких местах
- Более выразительный код - явно показывает связь между паттерном и привязкой
Когда использовать
Оператор @ особенно полезен когда:
- Нужно проверить сложный паттерн и использовать значение внутри блока
- Требуется избежать повторного вычисления или доступа к значению
- Паттерн сложный, но нужно сохранить доступ к оригинальному значению
Этот оператор делает код более выразительным и эффективным в ситуациях сложного паттерн-матчинга.