Hôm nay chúng ta sẽ tìm hiểu về std::Option - Một enum thường được được sử dụng để biểu thị 1 giá trị Some(T) hoặc là một giá trị None

pub enum Option<T> {
    None,
    Some(T),
}

Initalization - Khởi tạo

Đầu tiên để khởi tạo ra Option<T> cách đơn giản là wrap nó vào Some như định nghĩa của nó

fn test_option_return_some() -> Some<u32> {
    Some(100) // return 100
}
// Hoặc không trở về gì cả
fn test_option_return_none() -> Some<u32> {
   None
}

Methods

Chúng ta sẽ điểm lại một số function quan trọng hay sử dụng

Hàm kiểm tra: is_none or is_some

pub const fn is_none(&self) -> bool
let x: Option<u32> = Some(2);
assert_eq!(x.is_none(), false);

let x: Option<u32> = None;
assert_eq!(x.is_none(), true);

Trong ví dụ trên ta khởi tạo biến x với kiểu Option<u32> hoặc None

Các hàm với map

map

pub fn map<U, F>(self, f: F) -> Option<U>
where
    F: FnOnce(T) -> U,

Giải thích: Hàm trên nhận vào một hàm f: F và sẽ trả về kiểu dữ Option<U>

Biến đổi từ Option<T> tới Option<U>.Ví dụ như cần lấy giá trị độ dài của một chuỗi Option<String> -> Option<u32>

// Cần lấy giá trị độ dài của một chuỗi "Hello, World!"
let maybe_some_string = Some(String::from("Hello, World!"));
// `Option::map` takes self *by value*, consuming `maybe_some_string`
// Sử dụng hàm map 
let maybe_some_len = maybe_some_string.map(|s| s.len());
assert_eq!(maybe_some_len, Some(13));
 
//Khi s là None -> None
let x: Option<&str> = None;
assert_eq!(x.map(|s| s.len()), None);

map_or

pub fn map_or<U, F>(self, default: U, f: F) -> U
where
    F: FnOnce(T) -> U,

Giải thích:

Tương tự hàm map nhưng có thêm giá trị mặc định

// Option<String> -> Option<u32> và giá trị mặc định là 3
let x = Some("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);

// Nếu Option<&str> là None thì giá trị mặc định là 42
let x: Option<&str> = None;
assert_eq!(x.map_or(42, |v| v.len()), 42);

map_or_else

pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where
    D: FnOnce() -> U,
    F: FnOnce(T) -> U,

Ý nghĩa:Tham số truyền vào là 2 hàm or lambdas. Cả 2 hàm đều trở về kiểu U. Hàm D mặc định sẽ được áo dụng khi Option<T>None

let k = 21;


let x = Some("foo");
// Function là || 2*k gấp đôi giá trị của k = 21, 
//  hàm thứ 2 lấy độ dài của chuỗi `foo`
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);

let x: Option<&str> = None;
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);