Rust Pattern Matching and Match Expressions
Understanding Pattern Matching in Rust:
In Rust, pattern-matching is a very potent feature which allows you to compare a data value with multiple patterns and execute appropriate code based on the pattern which corresponds.
It is similar to switch statements in other languages but more powerful and flexible.
Using Match Expressions for Control Flow:
Match Expressions:
The match keyword allows you to perform pattern matching.The two part composition of match is a pattern and an expression for evaluation if the pattern is met.
Example:
fn main() {
let number = 7;
match number {
1 => println!("One!"),
2 => println!("Two!"),
3 => println!("Three!"),
4 | 5 | 6 => println!("Four, Five, or Six!"),
7..=10 => println!("Seven to Ten!"),
_ => println!("Something else!"),
}
}
- Patterns: Every pattern has the expression for its execution as well as the current binding value.
- Wildcards: _ is a catch-all pattern that matches any value not covered by other patterns.
- Ranges: 7..=10 matches any value from 7 to 10, inclusive.
Destructuring and Matching on Enums and Structs
Enums:
Enums, which are frequently paired with pattern matching to deal with variant types are a good example.
Example:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let msg = Message::Move { x: 10, y: 20 };
match msg {
Message::Quit => println!("Quit"),
Message::Move { x, y } => println!("Move to x: {}, y: {}", x, y),
Message::Write(text) => println!("Write: {}", text),
Message::ChangeColor(r, g, b) => println!("Change color to red: {}, green: {}, blue: {}", r, g, b),
}
}
- Destructuring: Message::Move { x, y } destructures the Move variant to access its fields.
Structs:
Structs can also be destructured in patterns.
Example:
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 };
match origin {
Point { x, y } => println!("Point at ({}, {})", x, y),
}
let Point { x, y } = origin;
println!("Destructured point at ({}, {})", x, y);
}
- Struct Pattern: Point { x, y } destructures the struct to access its fields directly.
Destructuring in Function Parameters:
You can also use patterns directly in function parameters.
Example:
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
}
fn main() {
let point = (3, 5);
print_coordinates(&point);
}
- Function Parameters: &(x, y) destructures a tuple passed as a parameter.
Nested Patterns:
Patterns can be nested to match complex data structures.
Example:
enum Message {
Move { x: i32, y: i32 },
Echo(String),
ChangeColor { red: u8, green: u8, blue: u8 },
}
fn main() {
let msg = Message::ChangeColor { red: 0, green: 255, blue: 127 };
match msg {
Message::Move { x, y } => println!("Move to x: {}, y: {}", x, y),
Message::Echo(text) => println!("Echo: {}", text),
Message::ChangeColor { red, green, blue } => println!("Change color to red: {}, green: {}, blue: {}", red, green, blue),
}
}
- Nested Destructuring: Message::ChangeColor { red, green, blue } accesses fields within the enum variant.
Rust patter matching lifts code readability and stability writhing about clear, expressive way to deal with different types of data and structures.