1 tháng học Rust - Enums và Pattern Matching

1 tháng học Rust - Enums và Pattern Matching

Tin ngắn hàng ngày dành cho bạn
  • Manus đã chính thức mở cửa cho tất cả người dùng rồi đấy mọi người. Cho những ai chưa biết thì đây là một công cụ viết báo cáo (làm mưa làm gió) giống như Deep Research của OpenAI á. Mỗi ngày được miễn phí 300 Credits để nghiên cứu. Mỗi lượt nghiên cứu tiêu tốn tuỳ thuộc vào độ phức tạp của yêu cầu. À với cả họ đang có chương trình tặng miễn phí Credits hay sao á. Như mình thì vào thấy được hẳn 2000.

    Mình dùng thử, so sánh với cùng một lệnh giống như đợt trước dùng bên Deep Research thì nội dung khác biệt nhau hoàn toàn. Manus báo cáo như kiểu viết văn hơn so với OpenAI là các gạch đầu dòng và bảng biểu.

    À lúc đăng ký xong có bắt nhập số điện thoại để xác minh, nếu lỗi thì các bạn đợi qua ngày thử lại xem có được không nhé.

    » Xem thêm
  • Mọi người chắc nghe nhiều về xu hướng tìm kiếm thông tin bằng AI chứ không cần công cụ tìm kiếm như Google nữa rồi đúng không? Không đâu xa ánh xạ vào bản thân thì thấy đúng thật, thi thoảng mới tìm kiếm thôi chứ còn đâu toàn hỏi tụi AI.

    Ngay từ đầu viết blog, thứ mà mình hướng đến là chia sẻ kinh nghiệm chứ không phải là những bài mang nặng tính kỹ thuật, máy móc, hướng dẫn từ đầu... Vì thời điểm đó đã có quá nhiều người làm nội dung này rồi và họ làm rất tốt, tại sao mình phải cố phát minh lại bánh xe? Một điều nữa là tin tưởng độc giả của mình có khả năng tìm hiểu vấn đề. Nếu bạn đọc đủ nhiều các bài viết trên blog thì thấy mình luôn cố gắng chèn thêm các liên kết tham khảo ngoài bài viết, nêu ra vấn đề mở và rất ít khi kết luận chắc chắn một điều gì đó.

    Mình đã cố gắng rèn luyện kỹ năng viết, kỹ năng trình bày và cả cách tương tác với độc giả để mang lại giá trị cho họ. Nhiều lúc ngồi lật lại các con số thống kê thấy lượng đọc bài viết tăng lên lại cảm thấy vui. Nhưng khi nguồn truy cập đến từ Google thì lại thấy buồn, vì điều đó chứng tỏ họ biết đến mình chỉ khi đang cố đi tìm giải pháp, có thể họ chỉ đọc chớp nhoáng, may ra tìm được cách giải quyết và thế là đóng cửa sổ trình duyệt rồi đi như một cơn gió.

    Chừng vài tháng đổ lại đây, một điều khiến mình rất vui đó là lượng người truy cập thẳng vào trang chủ mà không thông qua công cụ tìm kiếm đang tăng dần lên, có nhiều hôm lượng truy cập tự nhiên còn cao hơn cả đến từ Google. Điều đó chứng tỏ độc giả đã có thói quen quay lại trang của mình nhiều hơn và họ tìm thấy được giá trị từ blog mang lại. Vui mừng khôn xiết 🤩

    Bên cạnh đó thì lượng truy cập vào chuyên mục Threads - tức là mục mình đang viết bài này đang cao hơn bao giờ hết. Điều đó chứng tỏ xu hướng đi theo tin nhanh là đúng đắn. Mình có thể ngồi cả ngày để viết tin ngắn cho bạn đọc vì nó rất nhanh mà tiện, không tốn công đi tìm tài liệu để viết, không tốn cả thời gian viết nữa, còn mình thì có rất nhiều thứ để chia sẻ 😅. Nhưng không vì thế mà bỏ bê các bài viết dài, vì dài thì có nhiều thông tin để chia sẻ hơn.

    Vài lời tâm sự thế thôi chứ hơn một tháng nay mình chưa viết bài viết mới nào vì công việc bận quá. Xong lâu dần cứ trì hoãn lại thành lười. À với cả tháng 5 này rất thích hợp để đọc các cuốn sách về cách mạng á. Có hôm đọc đến 2 giờ sáng mới đi ngủ 🥱

    » Xem thêm
  • Mình mới nhìn thấy một trang web khá thú vị nói về các cột mốc đáng nhớ trong lịch sử phát triển Internet toàn cầu: Internet Artifacts

    Chỉ từ 1977 - khi Internet còn nằm trong hộp thí nghiệm thì nhìn xem - giờ đây Internet đã khiến mọi thứ phát triển đến mức nào 🫣

    » Xem thêm

Vấn đề

Về enums - một cấu trúc dữ liệu liệt kê mà có thể ai cũng biết. Enums cho phép xác định một loại bằng cách liệt kê các biến thể có thể có của nó. Trong mỗi ngôn ngữ lập trình, enums có cách khai báo và sử dụng khác nhau. Đối với Rust, enums được sử dụng khá thường xuyên vì nhiều lợi ích mà nó mang lại.

Bài viết ngày hôm nay chúng ta sẽ cùng nhau tìm hiểu về enums, xem nó có gì hay ho hơn so với các ngôn ngữ khác không nhé!

Enums

Một enums được khai báo như sau:

enum IpAddrKind {
    V4,  
    V6,  
}

Sau đó có thể sử dụng:

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

Enums trong Rust cũng lưu trữ được dữ liệu.

enum IpAddr {
    V4(String),  
    V6(String),  
}

let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));

Thậm chí, chúng ta còn có thể khai báo thêm phương thức cho nó.

enum IpAddr {
    V4(String),  
    V6(String),  
}

impl IpAddr {
    fn call(&self) {
        println!("Hello from IpAddr!");
    }
}

let home = IpAddr::V4(String::from("127.0.0.1"));
home.call();

Option là một enums được định nghĩa sẵn ở trong Rust, nó có một sứ mệnh quan trọng trong việc xử lý dữ liệu null.

Một Option có dạng Generic như sau.

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

Nhiều ngôn ngữ lập trình khác, chúng ta quá quen thuộc với kiểu dữ liệu null đại diện cho việc không có giá trị nào. Rust không có kiểu dữ liệu null, hầu hết trường hợp cần sử dụng null thì sẽ chuyển qua sử dụng enums Option.

None đại diện cho “không có gì” còn Some đại diện cho sự hiện hữu của một dạng dữ liệu nào đó. Lấy ví dụ.

let none: Option<i8> = None;
let five: Option<i8> = Some(5);
let six: Option<i8> = Sone(6);

Và dĩ nhiên chúng ta không thể thực hiện các phép tính trực tiếp trên kiểu dữ liệu Option này một cách bình thường.

// error
let sum = none + five;

// error
let sum = five + six;

Vậy thì làm cách nào để sử dụng được enums nói chung cũng như Option nói riêng?

Matching

Hầu hết việc xác định enums nhằm mục đích phân loại và xử lý dữ liệu theo các dạng được định nghĩa từ trước, chính vì thế Rust có cấu trúc xử lý loại rất mạnh mẽ là match hay còn gọi là “khớp mẫu”.

enum Coin {
    Penny,  
    Nickel,  
    Dime,  
    Quarter,  
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,  
        Coin::Nickel => 5,  
        Coin::Dime => 10,  
        Coin::Quarter => 25,  
    }
}

Hàm value_in_cents nhận vào một enums có kiểu Coin từ đó trả về giá trị tương ứng với tên của các đồng xu bằng cách sử dụng cú pháp match.

Đối với Option, chúng ta cũng sử dụng match để xử lý các trường hợp NoneSome, cũng như thực hiện các phép tính cơ bản mà Some nắm giữ như ví dụ ở đầu bài viết.

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,  
        Some(i) => Some(i + 1),  
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

Hàm plus_one nhận vào một Option<i32> và cộng thêm 1 vào giá trị của nó. Bằng cách khớp mẫu, hàm trả về None nếu như x là None, ngược lại nếu x là loại Some, tức là nó có giá trị thì sẽ trả về giá trị Some mới bằng cách cộng thêm 1.

Cho dễ hình dung, match gần giống với lệnh swich…case trong JavaScript. Trong khi switch đưa ra một giá trị khi nào khớp với giá trị trong case thì hàm xử lý đó ngay lập tức được thực thi. Nếu như switch…case có trường hợp default, nghĩa là khi các giá trị trong tất cả case không khớp thì cuối cùng hàm xử lý default được thực hiện. Trong Rust cũng có, người ta gọi là “Placeholder” hay “trình giữ chỗ”.

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),  
    7 => remove_fancy_hat(),  
    other => move_player(other),  
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}

Quay trở lại với trường hợp sử dụng Option, đôi khi chúng ta không quan tâm đến None lắm mà chỉ đơn giản là muốn thao tác với dữ liệu nếu có của Some. Ví dụ dưới đây luôn phải khai báo thêm một trình giữ chỗ để “không phải làm gì”.

let config_max = Some(3u8);
match config_max {
    Some(max) => println!("The maximum is configured to be {}", max),  
    _ => (),  
}

Điều này lặp lại một cách nhàm chán và thừa thãi, thay vào đó, Rust gợi ý chúng ta sử dụng kết hợp iflet để chỉ xử lý riêng cho một trường hợp cụ thể của một enums.

let config_max = Some(3u8);
if let Some(max) = config_max {
    println!("The maximum is configured to be {}", max);
}

Cuối cùng, vẫn có một lưu ý quan trọng về quyền sở hữu khi khớp mẫu khi Some giữ các giá trị tham chiếu. Bạn đọc có thể tham khảo thêm tại The Rust Programming Language - How Matches Interact with Ownership.

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Ẩn danh1 năm trước
Mình cũng bắt đầu tìm hiểu về rust, bạn có muốn lập nhóm ngồi cf trao đổi để học không?
Trả lời
Avatar
Xuân Hoài Tống1 năm trước
Chào bạn, rất vui khi nhận được lời đề nghị của bạn. Mình viết ra series tự học Rust để tạo cam kết cũng như ghi chép lại những gì học được, qua đó tóm tắt lại một cách cô đọng cho người đọc tham khảo. Tuy nhiên thì mình có nhiều lý do để rất khó lập được nhóm và cùng nhau trao đổi, như công việc và gia đình. Nhưng không sao, mình vẫn có thời gian cuối ngày để viết blog cũng như rất sẵn sàng trao đổi với bạn (dù không được realtime cho lắm). Hoặc nếu bạn cũng viết blog thì có thể để lại địa chỉ để cùng nhau học hỏi thêm :D