Patterns and Matching
The notes reflect the topics in Chapter 18
All the places patterns can be used.
// Simple match
match x {
None => None,
Some(i) => Some(i + 1),
}
// if let
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 {
println!("Tuesday is green day!");
} else if let Ok(age) = age {
if age > 30 {
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
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("{}", top);
}
// for loops
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}
// let statement
let (x, y, z) = (1, 2, 3);
// function parameters
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
}
fn main() {
let point = (3, 5);
print_coordinates(&point);
}Refutability
Just an idea so you know what it means in error message.
Patterns come in two forms: refutable and irrefutable. Patterns that will match for any possible value passed are irrefutable. An example would be
xin the statementlet x = 5; becausexmatches anything and therefore cannot fail to match. Patterns that can fail to match for some possible value are refutable. An example would beSome(x)in the expressionif let Some(x) = a_valuebecause if the value in thea_valuevariable isNonerather thanSome, theSome(x)pattern will not match.
Pattern Syntax
So this is mostly reference.
// Interesting syntax
match x {
1 | 2 => println!("one or two"),
3..7 => println!("three to 7"),
_ => println!("anything"),
}
// Struct
let p = Point { x: 0, y: 7 };
let Point { x: a, y: b } = p;
// we can also use the same variable name
let Point { x, y } = p;
// We can even only destruct part of the variable
match p {
Point { x, y: 0 } => println!("On the x axis at {}", x),
Point { x: 0, y } => println!("On the y axis at {}", y),
Point { x, y } => println!("On neither axis: ({}, {})", x, y),
}
// Enum
enum Message {
Quit,
Move { x: i32, y: i32 }, // struct-like
Write(String), // tuple-like
ChangeColor(i32, i32, i32), // Also tuple-like
ChangeColorPro(Color),
}
enum Color {
Rgb(i32, i32, i32),,
Hsv(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 {} and in the y direction {}",
x, y
);
}
Message::Write(text) => println!("Text message: {}", text),
Message::ChangeColor(r, g, b) => println!(
"Change the color to red {}, green {}, and blue {}",
r, g, b
),
Message::ChangeColorPro(Color::Rgb(r, g, b)) => println!(
"Change the color to red {}, green {}, and blue {}",
r, g, b
),
}
}
_ can be used as a wild pattern to ignore whatever value is there.
We can tell the compiler to ignore unused value by prefixing with _. Something
like let _x = 5.
We can even ignore using .. like this:
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, .., last) => {
println!("Some numbers: {first}, {last}");
}
}It even has match guards :exploding_head:.
let num = Some(4);
match num {
Some(x) if x % 2 == 0 => println!("The number {} is even", x),
Some(x) => println!("The number {} is odd", x),
None => (),
}In C++ land I guess we can have custom trait with some std::enable_if_t and
std::is_same_of.
We can also bind whatever is matched in a variable by using @.
fn main() {
enum 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),
}
}Note how in the first arm we are able to both match and store the value into
id_variable.