本文最后更新于 2024-03-29,本文发布时间距今超过 90 天, 文章内容可能已经过时。最新内容请以官方内容为准

Rust Study Day6

Summary

I’ve been studying Rust every day, but either due to being too busy with work to record or the content not being suitable for documentation, I haven’t been able to publish daily plans for the past two days. However, I still learned something today, so it’s time to make some records.

1. special enum type in Rust

enum Result<T, E> {
    Ok(T),     // Represents a successful result with a value of type T
    Err(E),    // Represents a failed result with an error of type E
}

enum Option<T> {
    Some(T),   // Represents a value of type T
    None,      // Represents the absence of a value
}

There are two special enums in Rust, Result and Option.
Result is used to represent the result of a function that may fail, and Option is used to represent the presence or absence of a value.

If you see the Result type, you should always remember the Option type.

2. Pattern Match

Some code:


Partial Variable Shadowing
fn main() {
    let x = Some(5);  // Define a variable x with a value of Some(5)
    let y = 10;       // Define a variable y with a value of 10

    match x {         // Start a match expression to pattern match against x
        Some(50) => println!("Got 50"),       // Check if x contains Some(50), print "Got 50"
        Some(y) => println!("Matched, y = {:?}", y),  // Bind inner value of Some to new variable y and print its value
        _ => println!("Default case, x = {:?}", x),   // Default case if no pattern matches
    }

    println!("at the end: x = {:?}, y = {:?}", x, y);  // Print values of x and y after match
}

// The output is:
> Matched, y = 5
> at the end: x = Some(5), y = 10

Value patterns

let x = 1;             // Define a variable x and assign it the value 1

match x {              // Start a match expression to pattern match against x
    1 | 2 => println!("one or two"),  // Match if x is either 1 or 2, print "one or two"
    3 => println!("three"),           // Match if x is 3, print "three"
    4..=8 => println!("grater than four but less than eight."),
    _ => println!("anything"),        // Default case if no pattern matches
}

// The output is:
> one or two

Deconstruct struct| enum| tuple

// Define a custom enum
enum MyEnum {
    Option1(i32),
    Option2(i32, i32),
    Option3 { x: i32, y: i32 },
}

// Define a custom struct
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let tuple = (3, 4);
    let enum_val = MyEnum::Option2(5, 6);
    let p = Point { x: 0, y: 7 };

    // Matching and deconstructing a tuple
    match tuple {
        (0, y) => println!("First element is zero, y = {}", y),  // Deconstructing tuple: extract y when the first element is 0
        (x, 0) => println!("Second element is zero, x = {}", x), // Deconstructing tuple: extract x when the second element is 0
        (x, y) => println!("Neither element is zero: ({}, {})", x, y),  // Deconstructing tuple: extract both x and y
    }

    // Matching and deconstructing an enum
    match enum_val {
        MyEnum::Option1(x) => println!("Option 1 with value {}", x),  // Deconstructing enum: extract value when it matches Option1 variant
        MyEnum::Option2(x, y) => println!("Option 2 with values {}, {}", x, y),  // Deconstructing enum: extract values when it matches Option2 variant
        MyEnum::Option3 { x, y } => println!("Option 3 with values {}, {}", x, y), // Deconstructing enum: extract values when it matches Option3 variant
    }

    // Matching and deconstructing a struct
    match p {
        Point { x, y: 0 } => println!("On the x axis at {}", x),  // Deconstructing struct: extract x when y is 0
        Point { x: 0, y } => println!("On the y axis at {}", y),  // Deconstructing struct: extract y when x is 0
        Point { x, y } => println!("On neither axis: ({}, {})", x, y),  // Deconstructing struct: extract both x and y
    }
}

// Output:
> Neither element is zero: (3, 4)
> Option 2 with values 5, 6
> On the y axis at 7

More syntax for destructuring:

fn main() {
   let x = 4;
    let y = false;

    match x {
        4 | 5 | 6  if y => println!("yes"), // equals (4 | 5 | 6 ) if y 
        _ => println!("no"),
    }

    let arr = [10, 20, 30, 40, 50];

    // Deconstructing array with first and last elements
    match arr {
        [first, .., last] => println!("First element: {}, Last element: {}", first, last),
        _ => println!("Array is empty"),
    }

    // Using '..' to skip elements
    match arr {
        [first, _, third, .., last] => println!("First: {}, Third: {}, Last: {}", first, third, last),
        _ => println!("Array is not long enough"),
    }

    // Match guard to check for specific conditions
    match arr {
        [_, _, _, _, last @ 50] => println!("Last element is exactly 50: {}", last),
        [_, _, _, _, last] if last > 40 => println!("Last element is greater than 40: {}", last),
        [_, _, _, _, last] if last < 40 => println!("Last element is less than 40: {}", last),
        _ => println!("Array is empty"),
    }

    // Binding with '@' for specific element
    match arr {
        [first, second @ 20, .., last] => println!("First: {}, Second: {}, Last: {}", first, second, last),
        _ => println!("No match found"),
    }
}

// Output:
> First element: 10, Last element: 50
> First: 10, Third: 30, Last: 50
> Last element is exactly 50: 50
> First: 10, Second: 20, Last: 50

More about pattern matching:
new feature for pattern guard and binding in match arms:

  1. Binding with ‘@’ while deconstructing tuple (Rust 1.56 Added)
  2. Using ‘@’ to bind new variable while also deconstructing (Rust 1.53 Added)
fn main() {
    let arr = [(1, 2), (3, 4), (5, 6)];

    // Binding with '@' while deconstructing tuple
    match arr[0] {
        (x, y) @ (1, _) => println!("First element is (1, {})", y),
        (x, y) @ (_, 4) => println!("Second element is ({}, 4)", x),
        _ => println!("No match found"),
    }

    // Using '@' to bind new variable while also deconstructing
    match 1 {
        num @ 1 | 2 => {
            println!("{}", num);
        }
        _ => {}
    }
}

// Output:
> First element is (1, 2)
> 1