Chapter 13: Rust Match
Rust match — perfect timing because match is basically Rust’s super-powered upgrade to switch/if-else chains.
In Rust, match is one of the most loved and most powerful features. People call it “pattern matching on steroids.” It lets you compare a value against many patterns, run code for the first matching one, and the compiler forces you to handle every possible case (exhaustive checking — huge safety win!).
Think of it like this:
- In other languages (C, Java, JavaScript): switch is limited — only integers/strings, no destructuring, fall-through bugs possible.
- In Rust: match works on anything (enums, structs, tuples, ranges, literals, variables…), destructures values, binds variables, has guards, and never forgets a case.
Let me explain it like your patient teacher sitting next to you with code open: slowly, with many real examples (copy-paste ready), Hyderabad-flavored analogies, and step-by-step building from simple to advanced.
1. Basic match Syntax
|
0 1 2 3 4 5 6 7 8 9 10 11 |
match VALUE { PATTERN1 => { code to run if PATTERN1 matches }, PATTERN2 => expression, // single line ok PATTERN3 if condition => ..., // guard (optional) _ => { catch-all / default }, } |
- match is an expression → can return a value (like if)
- All arms must return the same type (or () if no value)
- Arms separated by ,
- Last arm can omit , if it’s a block
2. Simple Example — Like switch on a number
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
fn main() { let number = 7; match number { 1 => println!("One! The beginning."), 2 | 3 | 5 | 7 | 11 => println!("This is a prime number! 🔢"), 13..=19 => println!("You're a teenager now! 🎉"), _ => println!("Just a normal number... 😴"), } } |
- = or (match any of these)
- ..= = inclusive range (13 to 19)
- _ = catch-all wildcard (must be last if used)
Run → try changing number to 13, 4, 1, 42 — see different arms fire.
3. Match is an Expression → Returns Values
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
fn main() { let temp = 38; let comfort_level = match temp { ..=25 => "Pleasant — go for a walk 🌳", 26..=32 => "Nice Hyderabad winter ☀️", 33..=38 => "Typical summer — AC time ❄️", _ => "Extreme heat — stay inside! 🔥😓", }; println!("Temp {}°C → {}", temp, comfort_level); } |
No return needed — last expression in arm is the value.
4. Matching Enums (The Real Power — Why Rust Loves match)
Enums + match = killer combo (like the coin example from The Book).
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
enum Coin { Penny, Nickel, Dime, Quarter(String), // e.g. "Telangana" state } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter(state) => { println!("Quarter from {}!", state); 25 } } } fn main() { let my_coin = Coin::Quarter(String::from("Telangana")); println!("Value: {} cents", value_in_cents(my_coin)); } |
- Destructures Quarter(state) → binds state variable
- Compiler error if you forget any variant → exhaustive!
5. Destructuring Structs & Tuples
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
struct Point { x: i32, y: i32, } fn main() { let origin = Point { x: 0, y: 0 }; match origin { Point { x: 0, y: y } => println!("On y-axis at {}", y), Point { x, y: 0 } => println!("On x-axis at {}", x), Point { x, y } => println!("At ({}, {})", x, y), } // Tuple example let pair = (0, 10); match pair { (0, y) => println!("On y-axis at {}", y), (x, 0) => println!("On x-axis at {}", x), _ => println!("Somewhere else"), } } |
- Point { x: 0, y } → literal match on x, bind y
- Shorthand: Point { x, y } = bind both with same name
6. Guards (if conditions on patterns)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
fn main() { let num = 15; match num { n if n % 2 == 0 => println!("Even number"), n if n % 3 == 0 => println!("Divisible by 3"), _ => println!("Odd & not divisible by 3"), } } |
- n if … = guard — only matches if condition true
- n = bound variable (can use in guard)
7. Matching References & Option/Result (Very Common)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
fn main() { let optional = Some(42); match optional { Some(value) => println!("Got {}", value), None => println!("Nothing here"), } // With ref let s = String::from("Hyderabad"); match &s { s if s.len() > 5 => println!("Long name: {}", s), _ => println!("Short name"), } } |
8. Advanced but Useful: @ Bindings & OR Patterns
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
let age = 25; match age { id @ 18..=25 => println!("Young adult (id = {})", id), id @ 0..=17 => println!("Minor (id = {})", id), _ => println!("Adult"), } |
- @ = bind whole pattern to name
Teacher Summary – Why match is Special in Rust
Rust match =
- Exhaustive (compiler forces all cases) → no forgotten enum variants
- Destructuring + binding + guards + ranges + or-patterns
- Expression → returns values cleanly
- Safe alternative to many if-else chains
- Heart of Rust error handling (match on Result, Option)
Practice tip: Create cargo new rust_match Try rewriting some if-else from earlier examples as match Then make an enum for Hyderabad food (Biryani, Haleem, Irani Chai…) and match on spiciness level.
Next ready?
- Loops (loop, while, for)?
- Ownership with match (moves, refs)?
- Or Option & Result in depth (where match shines most)?
Just say — your Rust guru from Hyderabad is here! 🦀🚀
