Pattern Matching
The match Expression
Section titled “The match Expression”match compares a value against a series of patterns and executes the arm whose pattern matches. Unlike a C switch, Rust’s match is an expression — it produces a value — and it is checked exhaustively by the compiler.
let x: i32 = 3;let description = match x { 1 => "one", 2 => "two", 3 => "three", _ => "something else",};println!("{}", description); // threeThe _ wildcard matches any value you have not listed explicitly. Without it (and without covering all cases), the code will not compile.
Matching Enum Variants and Binding Data
Section titled “Matching Enum Variants and Binding Data”The real power of match comes from destructuring enum variants and binding their data to local names:
enum Coin { Penny, Quarter(String),}
match coin { Coin::Penny => println!("Penny"), Coin::Quarter(state) => println!("Quarter from {}", state),}The identifier state in Coin::Quarter(state) is a binding — it receives the String value carried by that variant. You can use it freely inside the arm body.
Range Patterns
Section titled “Range Patterns”Patterns can match integer ranges with ..=:
match score { 90..=100 => "A", 80..=89 => "B", _ => "C or below",}The _ Wildcard
Section titled “The _ Wildcard”_ is a catch-all that matches anything without binding it. Place it last; any arm after _ would be unreachable and the compiler warns you.
if let — Matching One Variant
Section titled “if let — Matching One Variant”When you only care about one variant, if let is more concise than a full match:
let temperature = Some(22);if let Some(t) = temperature { println!("Temperature: {}C", t);}This binds t to the inner value if the pattern matches, and does nothing on None. You can attach an else branch for the non-matching case.
Match Guards
Section titled “Match Guards”A guard is an extra if condition on a match arm. It further narrows which values the arm accepts:
match number { n if n < 0 => println!("negative: {}", n), 0 => println!("zero"), n => println!("positive: {}", n),}Guards run after the structural pattern matches, so the binding (n) is available inside the guard condition.
#[derive(Debug)]enum Coin { Penny, Nickel, Dime, Quarter(String),}
fn value_in_cents(coin: &Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter(state) => { println!("Quarter from {}!", state); 25 } }}
fn describe_number(n: i32) -> &'static str { match n { 0 => "zero", 1..=9 => "single digit", 10..=99 => "double digit", _ => "large", }}
fn main() { let coins = vec![ Coin::Penny, Coin::Nickel, Coin::Quarter(String::from("Alaska")), Coin::Dime, ];
for coin in &coins { println!("{:?} = {} cents", coin, value_in_cents(coin)); }
for n in [0, 7, 42, 100] { println!("{} is {}", n, describe_number(n)); }
let temperature = Some(22); if let Some(t) = temperature { println!("Temperature: {}C", t); }}Compiling…