Day 1:巨集(Macros)入門

學習目標

  • 理解巨集的用途(產程式碼的程式碼)
  • 用 macro_rules! 寫簡單巨集
  • 認識宣告式巨集的語法

今日重點

巨集是什麼?

巨集是「寫程式的程式碼」。執行時(編譯階段)展開成 Rust 程式碼。println!vec! 都是巨集。

陳述式巨集(macro_rules!)

macro_rules! say_hello {
    () => {
        println!("Hello!");
    };
}

fn main() {
    say_hello!();   // 展開成 println!("Hello!")
}

帶參數的巨集(match pattern)

macro_rules! create_function {
    ($func_name:ident) => {
        fn $func_name() {
            println!("You called {:?}", stringify!($func_name));
        }
    };
}

create_function!(foo);
create_function!(bar);

fn main() {
    foo();
    bar();
}

$func_name:ident 表示「匹配一個識別字」。巨集會依模式展開。

重複模式

macro_rules! hello_vec {
    ($($item:expr),*) => {
        vec![$($item),*]
    };
}

fn main() {
    let v = hello_vec!(1, 2, 3);   // vec![1, 2, 3]
    println!("{:?}", v);
}

$(...) 表示「重複部分」,* 表示零到多次。

練習

// 1. 寫一個 min! 巨集,取兩個數的較小者
macro_rules! min {
    ($x:expr, $y:expr) => {
        if $x < $y { $x } else { $y }
    };
}
println!("{}", min!(10, 20));   // 10

// 2. 寫一個 repeat_print!(msg, n) 印 n 次
2. 說明 $x:expr$func_name:ident$(...)* 各代表什麼。

自我檢查

  • 理解巨集「展開」的機制
  • 會寫 macro_rules! 基本巨集
  • 認識 $item:expr / ident / 重複語法
  • 知道 println!/vec! 就是巨集

深入連結

  • The Book 第 19 章「Macros」