The match statement in Rust is a powerful control flow construct used for pattern matching. It allows you to compare a value against a series of patterns and execute code based on the first matching pattern. The match statement is similar to a switch statement in other programming languages but is significantly more flexible and robust.
What is the match Statement?
The match statement lets you handle multiple conditions or cases elegantly by matching a value against patterns. It ensures exhaustive checking, meaning all possible values must be accounted for, making your code safer and less prone to errors.
Syntax of match
match value {
pattern1 => action1,
pattern2 => action2,
_ => default_action,
}
- value: The value being matched.
- pattern: A pattern to match the value.
- =>: Indicates the action to perform for a matching pattern.
_
: A wildcard pattern that matches any value (used as a default case).
Example: Basic Usage
Matching Integers
fn main() {
let number = 3;
math number {
1 => println!("The number is one."),
2 => println!("The number is two."),
3 => println!("The number is three."),
_ => println!("The number is something else."),
}
}
Output:
The number is three.
Matching Multiple Patterns
You can use the |
operator to match multiple patterns.
Example: Odd or Even Numbers
fn main() {
let number = 2;
match number {
1 | 3 | 5 | 7 | 9 => println!("The number is odd."),
2 | 4 | 6 | 8 | 10 => println!("The number is even."),
_ => println!("The number is outside the range."),
}
}
Output:
The number is even.
Matching Ranges
Use the . .= operator to match a range of values.
Example: Grade Classification
fn main() {
let score = 85;
match score {
90..=100 => println!("Grade: A"),
75..=89 => println!("Grade: B"),
50..=74 => println!("Grade: C"),
_ => println!("Grade: F"),
}
}
Output:
Grade: B
6. Using match with Enums
The match statement is particularly useful with enums, allowing you to handle each variant explicitly.
Example: Traffic Light System
enum TrafficLight {
Red,
Yellow,
Green,
}
fn main() {
let light = TrafficLight::Red;
match light {
TrafficLight::Red => println!("Stop!"),
TrafficLight::Yellow => println!("Prepare to stop."),
TrafficLight::Green => println!("Go!"),
}
}
Output:
Stop!
7. Matching with Option
The Option enum is commonly used in Rust for handling values that may or may not be present.
Example: Handling an Optional Value
fn main() {
let value: Option<i32> = Some(5);
match value {
Some(x) => println!("The value is {}.", x),
None => println!("No value found."),
}
}
Output:
The value is 5.
Matching with Structs
You can deconstruct structs in a match
statement to extract values.
Example: Point Coordinates
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 10, y: 20 };
match point {
Point { x: 0, y } => println!("Point lies on the y-axis at {}", y),
Point { x, y: 0 } => println!("Point lies on the x-axis at {}", x),
Point { x, y } => println!("Point is at ({}, {}).", x, y),
}
}
Output:
Point is at (10, 20).
Exhaustiveness in match
Rust enforces exhaustive pattern matching, meaning all possible cases must be covered. If you miss a case, Rust will throw a compile-time error.
Using _ as a Catch-All Pattern
The _ pattern acts as a wildcard and matches any value not explicitly handled.
Example: Default Case
fn main() {
let number = 7;
match number {
1 => println!("One"),
2 => println!("Two"),
_ => println!("Something else"),
}
}
Output:
Something else
match as an Expression
The match statement can return values, which makes it very versatile for variable assignments.
Example: Determine Sign
fn main() {
let number = -10;
let result = match number {
n if n > 0 => "Positive",
n if n < 0 => "Negative",
_ => "Zero",
};
println!("The number is {}.", result);
}
Output:
The number is Negative.
Key Benefits of match
- Readable Code: Replaces complex nested if-else structures.
- Exhaustive Checking: Eliminates runtime errors from unhandled cases.
- Powerful and Versatile: Supports ranges, patterns, and destructuring.