Rust LogoPattern Syntax in Rust

Rust's pattern syntax is a powerful and versatile feature that allows you to match against the structure of values, extract data, and bind variables in a concise and expressive way. Patterns are fundamental to control flow and data manipulation in Rust, enabling robust and clear handling of complex data.

What are Patterns?
A pattern is a special syntax that describes the shape of a value you're looking for. When a value is compared against a pattern, Rust attempts to 'match' the value's structure with the pattern's structure. If they match, parts of the value can be 'destructured' (broken down) and bound to variables.

Where Patterns Are Used
Patterns appear in various places in Rust:
* `match` expressions: This is the most common and powerful context for pattern matching, allowing exhaustive checks against multiple patterns.
* `if let` expressions: Used for conditional execution when you only care about a single pattern match and want to ignore all others.
* `while let` loops: Similar to `if let`, but it continues looping as long as the pattern matches.
* `for` loops: Patterns are used to destructure elements yielded by an iterator.
* `let` statements: Patterns are used to bind variables and destructure data when initializing them.
* Function parameters: Patterns can be used in function signatures to destructure arguments directly.

Types of Patterns
Rust supports a rich set of pattern types:

1. Literal Patterns: Match against exact, constant values.
* Examples: `5`, `'a'`, `true`, `"hello"`

2. Variable Patterns: Bind the matched value (or part of it) to a new variable.
* Example: `let x = 5;` (here `x` is a variable pattern)
* Wildcard Pattern (`_`): Matches any value but doesn't bind it to a variable. Useful for explicitly ignoring parts of a value.
* Wildcard Variable (`_variable`): A variable starting with an underscore (e.g., `_x`) still binds the value but hints to the compiler that it might be intentionally unused, suppressing unused variable warnings.

3. Struct Patterns: Destructure the fields of a struct or struct-like enum variant.
* Example: `Point { x, y: 0, .. }` (shorthand `x` is `x: x`, `..` ignores other fields)

4. Enum Patterns: Match specific enum variants, optionally destructuring their associated data.
* Example: `Option::Some(value)`, `Result::Ok(data)`, `Message::Quit`

5. Tuple Patterns: Destructure the elements of a tuple.
* Example: `(x, y)`, `(_, status, 0)`

6. Array/Slice Patterns: Match against array or slice elements. For fixed-size arrays, `[a, b, c]` destructures. For slices or fixed-size arrays where some elements are to be ignored, `[first, .., last]` can be used (Rust 1.55+).

7. Reference Patterns: Match against references, destructuring the value they point to.
* Example: `&val` (matches an immutable reference), `&mut val` (matches a mutable reference)

8. Range Patterns: Match a value that falls within a specified range.
* Example: `1..=5` (inclusive range for numbers), `'a'..='z'` (inclusive range for characters).

9. OR Patterns (`|`): Combine multiple patterns, matching if any one of them matches.
* Example: `1 | 2 | 3`, `Color::Red | Color::Blue`

10. Binding Patterns (`@`): Binds a value to a variable *while also* matching against it with another pattern.
* Example: `num @ 1..=10` (binds the matched value to `num` if it's within the range).

11. `if` Guards: An optional conditional expression added to a `match` arm *after* the pattern. The pattern must match, and then the `if` guard must evaluate to `true` for the arm to be executed.
* Example: `Some(val) if val % 2 == 0 => ...`

12. `..` (Range Rest Pattern): Used within struct, tuple, and array patterns to ignore the remaining fields or elements without listing them explicitly.

Refutability of Patterns
Patterns are categorized by whether they are 'refutable' or 'irrefutable':
* Irrefutable Patterns: These patterns are guaranteed to match for *any* possible value given to them. Examples include `x` (a variable pattern), `(x, y)` for a tuple, or `Struct { .. }`. Irrefutable patterns are used in `let` statements, `for` loops, and function parameters, as these contexts expect a match to always succeed.
* Refutable Patterns: These patterns might *fail* to match a given value. Examples include `Some(x)` (an `Option` might be `None`), or `Point { x: 0, .. }` (the `x` field might not be `0`). Refutable patterns are used in `match` arms, `if let`, and `while let`, where the possibility of non-matching patterns is handled.

Rust's pattern syntax significantly enhances code readability and safety by ensuring comprehensive handling of data structures.

Example Code

```rust
// Define some data structures for demonstration
struct Point {
    x: i32,
    y: i32,
    z: Option<i32>,
}

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

fn main() {
    println!("--- 1. Literal Patterns ---");
    let x = 3;
    match x {
        1 => println!("Matched: One"),
        2 => println!("Matched: Two"),
        3 => println!("Matched: Three"),
        _ => println!("Matched: Other"),
    }

    println!("\n--- 2. Variable Patterns & Wildcard Pattern ---");
    let value = 100;
    let y = value; // `y` is a variable pattern, irrefutable
    println!("Bound y: {}", y);

    let some_tuple = (1, 2, 3);
    let (first, _, third) = some_tuple; // `_` ignores the second element
    println!("First: {}, Third: {}", first, third);

    println!("\n--- 3. Struct Patterns ---");
    let p1 = Point { x: 0, y: 7, z: Some(10) };
    let p2 = Point { x: 5, y: 5, z: None };
    let p3 = Point { x: 1, y: 2, z: Some(3) };

    match p1 {
        Point { x: 0, y: val_y, z: Some(val_z) } => {
            println!("Point at origin x, y: {}, z is Some({})", val_y, val_z);
        },
        Point { x: val_x, y: val_y, z: None } if val_x > val_y => {
            println!("Point x: {}, y: {} where x > y, z is None", val_x, val_y);
        },
        Point { x, .. } => {
            // `..` ignores `y` and `z` fields
            println!("Point with x: {}, other fields ignored (p3 matches here)", x);
        },
    }

    // Using struct pattern in `let`
    let Point { x: p3_x, y: p3_y, .. } = p3;
    println!("Destructured p3 into x: {}, y: {}", p3_x, p3_y);

    println!("\n--- 4. Enum Patterns ---");
    let msg = Message::Move { x: 10, y: 20 };
    let msg_quit = Message::Quit;
    let msg_write = Message::Write(String::from("Hello, Rustaceans!"));

    match msg {
        Message::Quit => println!("Received Quit message"),
        Message::Move { x, y } => println!("Received Move message to ({}, {})", x, y),
        Message::Write(text) => println!("Received Write message: '{}'", text),
        Message::ChangeColor(r, g, b) => println!("Received ChangeColor to ({}, {}, {})", r, g, b),
    }

    // `if let` for a single variant
    if let Message::Write(text) = msg_write {
        println!("Using if let for Write message: '{}'", text);
    }

    println!("\n--- 5. Tuple Patterns ---");
    let pair = (10, 20);
    let triple = (5, 'A', true);

    match pair {
        (x, 0) => println!("First is {}, second is 0", x),
        (10, y) => println!("First is 10, second is {}", y),
        _ => println!("Other pair"),
    }

    let (num, character, boolean) = triple; // Destructuring with tuple pattern
    println!("Triple: num={}, char='{}', bool={}", num, character, boolean);

    println!("\n--- 6. Array/Slice Patterns ---");
    let arr = [1, 2, 3, 4, 5];
    match arr {
        [1, second, third, .., last] => println!("First: 1, Second: {}, Third: {}, Last: {}", second, third, last), // Rust 1.55+
        [_, _, _, _, _] => println!("Five elements array"),
    }

    let [a, b, c, d, e] = arr; // Destructuring fixed-size array
    println!("Array elements: {},{},{},{},{}", a, b, c, d, e);

    println!("\n--- 7. Reference Patterns ---");
    let num = 42;
    let ref_num = #
    let mut mut_num = 100;
    let ref_mut_num = &mut mut_num;

    match ref_num {
        &val => println!("Value referenced: {}", val), // `&val` destructures the reference
    }

    match ref_mut_num {
        &mut val => {
            *val += 1;
            println!("Mutated value through mutable reference: {}", val);
        }
    }

    println!("\n--- 8. Range Patterns ---");
    let temperature = 25;
    match temperature {
        0..=10 => println!("It's cold"),
        11..=25 => println!("It's mild"),
        26..=35 => println!("It's hot"),
        _ => println!("Extreme temperature"),
    }

    let grade = 'B';
    match grade {
        'A' | 'B' | 'C' => println!("Passing grade"),
        'D' | 'F' => println!("Failing grade"),
        _ => println!("Invalid grade"),
    }

    println!("\n--- 9. OR Patterns ---");
    let traffic_light = "red";
    match traffic_light {
        "red" | "yellow" => println!("Stop or prepare to stop"),
        "green" => println!("Go!"),
        _ => println!("Unknown light"),
    }

    println!("\n--- 10. Binding Patterns (@) ---");
    let age = 30;
    match age {
        teen_age @ 13..=19 => println!("Teenager: {}", teen_age),
        adult_age @ 20..=64 => println!("Adult: {}", adult_age),
        _ => println!("Other age"),
    }

    enum MyOption { MySome(i32), MyNone }
    let maybe_val = MyOption::MySome(7);
    match maybe_val {
        MyOption::MySome(val @ 1..=10) => println!("Value {} is small", val),
        MyOption::MySome(val) => println!("Value {} is not small", val),
        MyOption::MyNone => println!("No value"),
    }

    println!("\n--- 11. `if` Guards ---");
    let number_option = Some(15);
    match number_option {
        Some(val) if val % 2 == 0 => println!("Even number: {}", val),
        Some(val) if val % 2 != 0 => println!("Odd number: {}", val),
        None => println!("No number"),
    }

    let status_code = 404;
    match status_code {
        s if s >= 200 && s < 300 => println!("Success: {}", s),
        s if s >= 400 && s < 500 => println!("Client Error: {}", s),
        _ => println!("Other status"),
    }
}
```