Doc.rust-lang.org/book/ch18-0…
There are several types of patterns:
- Literals
- Destructured arrays, enums, structs, or tuples
- Variables
- Wildcards
- Placeholders
What are patterns && where are patterns used
Patterns are common in Rust, such as in our common assignment statements: let x = 5; X is a pattern. Rust compares the value of an expression to the pattern and binds the value to X if it is the pattern. X does not specify a type, so the value of any expression can be matched successfully. Function parameters are also a pattern, for example: fn add(x: i32), x is a pattern, only the value of the pattern x can be passed in the parameter. For loop for x in y, x is also a pattern. There are several other more common ways to use patterns:
match
Arms
match VALUE {
PATTERN => EXPRESSION,
PATTERN => EXPRESSION,
PATTERN => EXPRESSION,
}
Copy the code
if let
fn main() {
let favorite_color: OptionThe < &str> = None;
let is_tuesday = false;
let age: Result<u8, _ > ="34".parse();
if let Some(color) = favorite_color {
println!("Using your favorite color, {}, as the background", color);
} 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"); }}Copy the code
while let
fn main() {
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("{}", top); }}Copy the code
Refutable && Irrefutable Pattern
Patterns come in two forms: refutable and irrefutable. Patterns that will match for any possible value passed are irrefutable. An example would be x in the statement let x = 5; because x matches anything and therefore cannot fail to match. Patterns that can fail to match for some possible value are refutable. An example would be Some(x) in the expression if let Some(x) = a_value because if the value in the a_value variable is None rather than Some, the Some(x) pattern will not match. In short, the pattern of rejection is to allow mismatches. The one thing that cannot be rejected is that it must match all the values passed in. Failure is not allowed.
Pattern Syntax
Here is mainly about the use of some trick mode, mode syntax, including: scope, placeholders and so on.
Matching Literals
fn main() {
let x = 1;
match x {
1= >println!("one"),
2= >println!("two"),
3= >println!("three"), _ = >println!("anything"),}}Copy the code
Matching Named Variables
fn main() {
let x = Some(5);
let y = 10;
match x {
Some(50) = >println!("Got 50"),
Some(y) => println!("Matched, y = {:? }", y), // This y is a shadow value._ = >println!("Default case, x = {:? }", x),
}
println!("at the end: x = {:? }, y = {:? }", x, y);
}
Copy the code
Mutiple Patterns
fn main() {
let x = 1;
match x {
1 | 2= >println!("one or two"),
3= >println!("three"), _ = >println!("anything"),}}Copy the code
Matching Ranges of Values with .. =
fn main() {
let x = 5;
match x {
1..=5= >println!("one through five"), _ = >println!("something else"),}}Copy the code
Destructuring to Break Apart Values
Destructuring Structs
struct Point {
x: i32,
y: i32,}fn main() {
let p = Point { x: 0, y: 7 };
let Point { x: a, y: b } = p;
assert_eq!(0, a);
assert_eq!(7, b);
let Point { x, y } = p;
assert_eq!(0, x);
assert_eq!(7, y);
}
Copy the code
Set default values to match.
struct Point {
x: i32,
y: i32,}fn main() {
let p = Point { x: 0, y: 7 };
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),
}
}
Copy the code
Destructuring Enums
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(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
),
}
}
Copy the code
Destructuring Nested Structs and Enums
enum Color {
Rgb(i32.i32.i32),
Hsv(i32.i32.i32),}enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(Color),
}
fn main() {
let msg = Message::ChangeColor(Color::Hsv(0.160.255));
match msg {
Message::ChangeColor(Color::Rgb(r, g, b)) => println!(
"Change the color to red {}, green {}, and blue {}",
r, g, b
),
Message::ChangeColor(Color::Hsv(h, s, v)) => println!(
"Change the color to hue {}, saturation {}, and value {}",
h, s, v
),
_ => (),
}
}
Copy the code
Destructuring Structs and Tuples
fn main() {
struct Point {
x: i32,
y: i32,}let ((feet, inches), Point { x, y }) = ((3.10), Point { x: 3, y: -10 });
}
Copy the code
Ignoring Values in a Pattern
Ignoring an Entire Value with _
fn foo(_ :i32, y: i32) {
println!("This code only uses the y parameter: {}", y);
}
fn main() {
foo(3.4);
}
Copy the code
Ignoring Parts of a Value with a Nested _
fn main() {
let mut setting_value = Some(5);
let new_setting_value = Some(10);
match (setting_value, new_setting_value) {
(Some(_), Some(_)) = > {println!("Can't overwrite an existing customized value"); } _ => { setting_value = new_setting_value; }}println!("setting is {:? }", setting_value);
}
Copy the code
Ignoring an Unused Variable by Starting Its Name with _
fn main() {
let _x = 5; // _x binds with 5.
let _ = 5; // _ doesn't bind with 5;
let y = 10;
}
Copy the code
Ignoring Remaining Parts of a Value with ..
fn main() {
struct Point {
x: i32,
y: i32,
z: i32,}let origin = Point { x: 0, y: 0, z: 0 };
matchorigin { Point { x, .. } = >println!("x is {}", x),
}
}
Copy the code
Note that only the following values can be omitted, not:.., x, ..
Extra Conditionals with Match Guards
fn main() {
let num = Some(4);
match num {
Some(x) if x < 5= >println!("less than five: {}", x),
Some(x) => println!("{}", x),
None= > (),}}Copy the code
@ Bindings
The at operator (@) lets us create a variable that holds a value at the same time we’re testing that value to see whether it matches a pattern.
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),
}
}
Copy the code