· Phạm Thành Nam · Ngôn ngữ Rust · 3 phút đọc

30 Ngày học Rust - Day 23: Quyền năng của Đấng Tạo Hóa (Declarative Macros)

Day 23: Macro là gì? Tại sao println! lại có dấu chấm than? Khám phá Metaprogramming, nghệ thuật viết Code sinh ra Code giúp giảm thiểu hàng ngàn dòng code tẻ nhạt.

Day 23: Macro là gì? Tại sao println! lại có dấu chấm than? Khám phá Metaprogramming, nghệ thuật viết Code sinh ra Code giúp giảm thiểu hàng ngàn dòng code tẻ nhạt.

Metaprogramming: Khi Code biết làm thơ

Khi bạn sử dụng hàm (Functions) trong Rust, hàm nhận dữ liệu đầu vào và trả ra kết quả. Nếu bạn nạp 3 tham số, hàm sẽ lấy 3 biến. Hàm ở Rust bị khoá cứng: bạn KHÔNG THỂ gọi một hàm với số lượng tham số biến thiên (Varargs) như ngôn ngữ C hay Javascript. Hàm cũng không thể tạo ngầm ra Biến tên mới.

Nhưng ở Ngày 1, bạn đã dùng Lệnh println!("Trời quăng {}", 5) và thậm chí là Mảng vec![1, 2, 3]. Cả 2 đều có dấu chấm than !.

Chúng không phải là Function bình thường. Chúng là Macros (Lệnh Khối vĩ mô). Macros có quyền nhai trọn 100 hay 1000 tham số, rồi trong tíc tắc lúc Compiler đọc ngang, nó BĂM ĐOẠN ĐÓ RA thành hàng vạn Dòng CODE CHUẨN MỰC lót vào chỗ bạn vừa đứng!

Nói cách khác: Hàm là Code chạy tính toán ra Data. Macro là Code tự đẻ ra Code để chạy.

Mô phỏng Declarative Pattern nhả xưởng Code ngầm

1. Declarative Macros: Macro dạng Mẫu Dấu macro_rules!

Loại Macro rẻ tiền và phổ biến nhất ở Rust. Bạn lập 1 Khối so Khớp Hình Mẫu (như RegEx), và điền Rule (Luật Đẻ Code).

Chúng ta sẽ tự chế lại Cái Cái Cọc vec! của Rust Lõi Nhé. Giờ ta đặt tên là tao_mang!:

// Tiếng Còi Khai Báo Sinh Macro
macro_rules! tao_mang {
    // 1. Phân khu Luật (Khớp Cấu Trúc Text Do Người CODE nhập vào)
    // $( ... ),* báo hiệu 1 Vòng Lặp Bất Tận quét từng Vế chữ được phẩy cách nhau 
    // Mảng ruột $x:expr Yêu cầu chữ nhập bên trong phải LÀ 1 BIỂU THỨC (Expression - như Số, Biến)
    ( $( $x:expr ),* ) => { 
        { 
            // 2. Chỗ Này Là Code Được IN ĐÈ BÙNG NỔ TRONG FILE LÚC COMPILE
            let mut v = Vec::new(); // Dịch: Tạo Mảng Két
            
            // Lặp Theo Số Tham Số Bị Quẳng Vô Khớp Pattern Phía Trên
            $(
                v.push($x); // Dịch: Gắp giá trị x đẩy Nhồi xuống V
            )*
            v // Trả Về Khối Két V
        }
    };
}

fn main() {
    // BẠN GỌI:
    let ds = tao_mang![10, 20, 30]; 
    
    // TRÌNH COMPILE NHÌN THẤY Y NHƯ VẬY (Tự Ráp Tự In Không Rác Không Bug):
    // let ds = { let mut v = Vec::new(); v.push(10); v.push(20); v.push(30); v };
}

Hãy Tưởng Tượng Việc Phải Viết 1 Trăm Lần Cái Phép Cầm push()... push(). macro_rules! Là Cái Máy Ủi Gỗ Băm Ra Bột Giấy Sức Mạnh Max Cấp.

Câu hỏi thường gặp (FAQ)

Có nên xài Macro ở Khắp Tọi Chừng Khắp Nơi Trong App Mình Lọc Nhọc Chứ?

TUYỆT ĐỐI KHÔNG. Code Hàm thường Tuân theo Ranh Giới Types Type, Compiler Bug nó Báo Rõ Ràng. Lỡ Bạn Gõ Sai Mã Khớp Macro? Bảng Lỗi Báo Có Thể Dài Hơn Sớ Thằng Phở, Không Ai Dò Tìm Nổi Lỗi (Ngay đến Thằng Tool Hint Phím VScode Cũng Mù Vì Đây Code Trộn). Bạn chỉ dùng Mã Sinh Macro khi Vấn Đề Lập Khung Lặp Sườn Quá Ngột ngạt mà Generic T Trait không Lách Đổi Trải được.


Sẵn sàng cho Ngày 24? Kiểu Declarative Gắn Khớp So Chữ Dài dòng Và Quá Kẹt Bọt. Ngày Mai, Lõi Bão Siêu Hạnh Cực Chảy Sẽ Hé Mở: Macro Thế Hệ 2 (Procedural Macros). Tước Quyền Lấy Data Trình Compiler Cưa Rách Nó Luôn Bằng: [Day 24: Kẻ Phanh Thây - Procedural Macros].

Chuỗi bài viết

30 Ngày Trở Thành Rustacean Tinh Hoa

Phần 23 / 30

30 bài viết
  1. Phần 1 30 Ngày học Rust - Day 1: Lời chào thế giới và Vũ khí Cargo
  2. Phần 2 30 Ngày học Rust - Day 2: Biến, Bất biến (Mutability) và Shadowing
  3. Phần 3 30 Ngày học Rust - Day 3: Luồng điều khiển (Control Flow) và sức mạnh của Match
  4. Phần 4 30 Ngày học Rust - Day 4: Ownership - Khái niệm định hình cỗ thần khí Rust
  5. Phần 5 30 Ngày học Rust - Day 5: Khóa học nhặt đồ chung với References & Borrowing
  6. Phần 6 30 Ngày học Rust - Day 6: Đắp nặn dự án với Structs và Methods
  7. Phần 7 30 Ngày học Rust - Day 7: Quyền năng vô song của Enums và Pattern Matching
  8. Phần 8 30 Ngày học Rust - Day 8: Quản lý dự án với Packages, Crates và Modules
  9. Phần 9 30 Ngày học Rust - Day 9: Các bộ sưu tập chung (Vectors, Strings, Hash Maps)
  10. Phần 10 30 Ngày học Rust - Day 10: Trị dứt điểm Ác mộng Lỗi (Error Handling)
  11. Phần 11 30 Ngày học Rust - Day 11: Generics - Ma thuật Đa hình kiểu dữ liệu
  12. Phần 12 30 Ngày học Rust - Day 12: Traits - Kẻ ban phát quyền năng và Lập pháp Hành vi
  13. Phần 13 30 Ngày học Rust - Day 13: Vượt qua Boss cuối 'Lifetimes' - Sinh Mệnh Biến
  14. Phần 14 30 Ngày học Rust - Day 14: Tận diệt Bug từ trứng nước bằng Automated Tests
  15. Phần 15 30 Ngày học Rust - Day 15: Thực chiến Build Command Line App (CLI) đầu đời
  16. Phần 16 30 Ngày học Rust - Day 16: Functional Magic chốn trần gian (Closures & Iterators)
  17. Phần 17 30 Ngày học Rust - Day 17: Quyền năng của Smart Pointers
  18. Phần 18 30 Ngày học Rust - Day 18: Chinh phục Da luồng (Concurrency) - Cú đâm quyết định của Rust
  19. Phần 19 30 Ngày học Rust - Day 19: Tranh cãi Lập trình hướng đối tượng (OOP) trong Rust
  20. Phần 20 30 Ngày học Rust - Day 20: Mổ xẻ nghệ thuật Advanced Pattern Matching
  21. Phần 21 30 Ngày học Rust - Day 21: Sức mạnh tối thượng của Advanced Traits
  22. Phần 22 30 Ngày học Rust - Day 22: Về Phe Bóng Tối với Unsafe Rust
  23. Phần 23 30 Ngày học Rust - Day 23: Quyền năng của Đấng Tạo Hóa (Declarative Macros)
  24. Phần 24 30 Ngày học Rust - Day 24: Siêu Năng Lực Procedural Macros (Macro Thủ Tục)
  25. Phần 25 30 Ngày học Rust - Day 25: Xây dựng TCP Web Server Đa Luồng (Phần 1: Lõi Socket)
  26. Phần 26 30 Ngày học Rust - Day 26: Xây dựng TCP Web Server Đa Luồng (Phần 2: Bắn trả File HTML)
  27. Phần 27 30 Ngày học Rust - Day 27: Xây dựng TCP Web Server Đa Luồng (Phần 3: The Thread Pool)
  28. Phần 28 30 Ngày học Rust - Day 28: Xây dựng TCP Web Server Đa Luồng (Phần 4: Graceful Shutdown)
  29. Phần 29 30 Ngày học Rust - Day 29: Lên đỉnh Web Server Thực Chiến với Axum và Tokio
  30. Phần 30 30 Ngày học Rust - Day 30: Vượt Vọng Vàng - Đúc Kết Hành Trình Rustacean Tinh Hoa

Bình luận

Quay lại Blog

Bài viết liên quan

Xem tất cả bài viết »