Patterns
Simple
A pattern in its most simple form:
#![allow(unused)] fn main() { let x = 5; }
let PATTERN = EXPRESSION;
Destructure Pattern
#![allow(unused)] fn main() { let (x, y, z) = (1, 2, 3); }
Ignore Pattern
#![allow(unused)] fn main() { let (x, ..) = (1, 2, 3); // OR let (x, _, _) = (1, 2, 3); }
Destructure Struct
struct Point { x: i32, y: i32, } fn main() { let p = Point { x: 0, y: 7 }; let Point { x, y } = p; assert_eq!(0, x); assert_eq!(7, y); }
You could change the variable names like this:
#![allow(unused)] fn main() { let Point { x: a, y: b } = p; println("{} {}", a, b); }
Function pattern
Here &(x, y): &(i32, i32)
is the pattern
fn print_coordinates(&(x, y): &(i32, i32)) { println!("Current location: ({}, {})", x, y); } fn main() { let point = (3, 5); print_coordinates(&point); }
Match values
With an or statement
#![allow(unused)] fn main() { let x = 1; match x { 1 | 2 => println!("one or two"), 3 => println!("three"), _ => println!("anything"), } }
With a range
#![allow(unused)] fn main() { let x = 5; match x { 1..=5 => println!("one through five"), _ => println!("something else"), } }
Match with a destructured struct
struct Point { x: i32, y: i32, } impl Point { fn where_am_i(&self) { match self { 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), } } } fn main() { let p = Point { x: 8, y: 0 }; p.where_am_i(); let p = Point { x: 0, y: 7 }; p.where_am_i(); let p = Point { x: 8, y: 7 }; p.where_am_i(); }
Destructure a struct inside an enum
enum Message { Move { x: i32, y: i32 }, ChangeColor(i32, i32, i32), } impl Message { fn print_me(&self) { match self { Message::Move { x, y } => { println!("Move in the x direction {} and in the y direction {}", x, y); } Message::ChangeColor(r, g, b) => { println!("Change the color to red {}, green {}, and blue {}", r, g, b) } } } } fn main() { let msg = Message::Move { x: 10, y: 15 }; msg.print_me(); let msg = Message::ChangeColor(0, 160, 255); msg.print_me(); }
Nested enum pattern matching
use Color::Hsv; use Color::Rgb; use Message::ChangeColor; enum Color { Rgb(i32, i32, i32), Hsv(i32, i32, i32), } enum Message { ChangeColor(Color), } impl Message { fn print_me(&self) { match self { ChangeColor(Rgb(r, g, b)) => { println!("Change the color to red {}, green {}, and blue {}", r, g, b) } ChangeColor(Hsv(r, g, b)) => { println!( "Change the color to hue {}, saturation {}, and value {}", r, g, b) } } } } fn main() { let msg = ChangeColor(Rgb(25, 50, 50)); msg.print_me(); let msg = ChangeColor(Hsv(50, 45, 180)); msg.print_me(); }
Ignoring
Underscore
Use the underscore to ignore certain patterns
#![allow(unused)] fn main() { let numbers = (2, 4, 8, 16, 32); match numbers { (first, _, third, _, fifth) => { println!("Some numbers: {}, {}, {}", first, third, fifth) } } }
..
Use just the x value from a Point:
#![allow(unused)] fn main() { struct Point { x: i32, y: i32, z: i32, } let origin = Point { x: 0, y: 0, z: 0 }; match origin { Point { x, .. } => println!("x is {}", x), } }
Match guards
Adds an extra check to an arm
#![allow(unused)] fn main() { let num = Some(4); match num { Some(x) if x < 5 => println!("less than five: {}", x), Some(x) => println!("{}", x), None => (), } }
Check if the value of x
matches 4 | 5 | 6
, but y being true takes precedence:
#![allow(unused)] fn main() { let x = 4; let y = false; match x { 4 | 5 | 6 if y => println!("yes"), _ => println!("no"), } }
Match Binding
@
gives access to variable which has been matched
enum Message { Hello { id: i32 }, } fn main() { 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), } }
Complex destructure
Making all values available through a destructure:
#![allow(unused)] fn main() { let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 }); }