Patterns are a special syntax in Rust for matching against the structure of types …
We can control the flow of a program by matching against patterns.
Patterns describe the shape of data
Ex: \(m \times n\) matrix vs. \(n \times p\) matrix
1
)(x, y) = (1, 2)
)match x ...
)_
)_
)match
expressionif let
expressionif let
expressionfn main() {
let favorite_color: Option<&str> = None;
let is_tuesday = false;
let age: Result<u8, _> = "34".parse();
if let Some(color) = favorite_color {
println!("Using your favorite color, {color}, as the background");
} else if is_tuesday { // unrelated to favorite_color
println!("Tuesday is green day!");
} else if let Ok(age) = age {
if age > 30 { // shadow variable age
println!("Using purple as the background color");
} else {
println!("Using orange as the background color");
}
} else {
println!("Using blue as the background color");
}
}
while let
expressionfor
looplet
fun
parametersPatterns that can fail to match for some possible value are refutable.
Patterns that will match for any possible value passed are irrefutable.
Some places require refutable patterns, some places require irrefutable patterns
Usage: respond to specific values
Usage: match any value
Usage: match against multiple patterns
Usage: match against a range of values
Usage: match against different parts
Usage: match against different parts
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let msg = Message::ChangeColor(0, 160, 255);
match msg {
Message::Quit => {
println!("The Quit variant has no data to destructure.");
}
Message::Move { x, y } => {
println!("Move in the x direction {x} and in the y direction {y}");
}
Message::Write(text) => {
println!("Text message: {text}");
}
Message::ChangeColor(r, g, b) => {
println!("Change the color to red {r}, green {g}, and blue {b}")
}
}
}
Usage: match against different parts
enum Color {
Rgb(i32, i32, i32),
Hsv(i32, i32, i32),
}
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(Color),
}
fn main() {
let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
match msg {
Message::ChangeColor(Color::Rgb(r, g, b)) => {
println!("Change color to red {r}, green {g}, and blue {b}");
}
Message::ChangeColor(Color::Hsv(h, s, v)) => {
println!("Change color to hue {h}, saturation {s}, value {v}")
}
_ => (),
}
}
Usage: match against different parts
Usage: ignore an entire value
Usage: ignore only part of a value
Usage: ignore a nested value
Usage: ignore multiple places in a single pattern
Usage: ignore an unused variable
Usage: use first part(s) of a value, ignore the rest
A match guard is an additional if condition, specified after the pattern in a match arm, that must also match for that arm to be chosen.
@
BindingsThe at operator @ lets us create a variable that holds a value at the same time as we’re testing that value for a pattern match
@
Bindingsenum Message {
Hello { id: i32 },
let msg = Message::Hello { id: 5 }
match msg {
Message::Hello {
id: id_variable @ 3..=7,
} => println!("Found an id in range: {id_variable}"),
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => println!("Found some other id: {id}"),
}