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:

  1. match Arms
match VALUE {
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
}

Copy the code
  1. 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
  1. 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