
Rust Study Day6
本文最后更新于 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:
- Binding with ‘@’ while deconstructing tuple (Rust 1.56 Added)
- 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