Day 3 · Concept 08
Pattern matching
match is exhaustive and destructuring. Structs, enums, tuples, arrays,
slices, references — all can be matched on, all in one syntax. The single feature
that makes Rust feel like a typed Haskell.
1 · Destructure anything
fn main() {
// Tuple destructure
let point = (3, 4);
let (x, y) = point;
println!("x={} y={}", x, y);
// Array destructure with rest
let arr = [1, 2, 3, 4, 5];
if let [first, .., last] = arr {
println!("first={} last={}", first, last);
}
// Struct destructure
struct User { name: String, age: u32 }
let u = User { name: "Alice".into(), age: 30 };
let User { name, age } = u;
println!("name={} age={}", name, age);
}2 · Match guards and ranges
fn describe(n: i32) -> &'static str {
match n {
0 => "zero",
1..=9 => "single digit",
10..=99 => "two digits",
n if n < 0 => "negative",
_ => "big",
}
}
fn main() {
for n in [0, 5, 42, 1000, -7] {
println!("{} -> {}", n, describe(n));
}
}3 · Binding with @ — capture while matching
enum Msg {
Hello { id: u32 },
}
fn handle(m: Msg) {
match m {
Msg::Hello { id: id_var @ 1..=10 } => println!("small id: {}", id_var),
Msg::Hello { id: id_var @ 11..=100 } => println!("medium id: {}", id_var),
Msg::Hello { id } => println!("other: {}", id),
}
}
fn main() {
handle(Msg::Hello { id: 5 });
handle(Msg::Hello { id: 50 });
handle(Msg::Hello { id: 999 });
}4 · let else — early return on the failing branch
fn first_word(s: &str) -> &str {
let Some(pos) = s.find(' ') else {
return s; // no space — return whole string
};
&s[..pos]
}
fn main() {
println!("[{}]", first_word("hello world"));
println!("[{}]", first_word("single"));
}5 · Common mistakes
- Forgetting exhaustiveness with
_. If you don't want to handle every variant, add_ =>— but think first whether you should. - Using
ifwherematchreads cleaner. Anif let Some(x) = opt { ... } else { ... }chain is often clearer as a full match. - Forgetting
refin patterns that need a reference. When destructuring without consuming, useref:let User { ref name, age } = u;.
6 · When it clicks
- You destructure tuples, structs, and enums in
letwithout thinking. - Match guards (
n if n < 0) feel native, not advanced. - You reach for
let ... elsefor early-exit on optional values.
Found this useful?