Day 2:建立可重用巨集範例
學習目標
- 練習不同 fragment types
- 用巨集做程式碼生成
- 了解巨集的侷限
今日重點
常見 fragment type 速查
| 片段 | 代表 |
|---|---|
$x:expr |
一個表達式 |
$n:ident |
一個識別字(變數/函式名) |
$t:ty |
一個型別 |
$lit:literal |
一個字面值 |
$pat:pat |
一個模式 |
生成 enum 變體的巨集
// 生成一個包含多個變體、全都能 Debug 的 enum
macro_rules! simple_enum {
($name:ident { $($variant:ident),* }) => {
#[derive(Debug)]
enum $name {
$($variant),*
}
};
}
simple_enum!(Status { Running, Stopped, Error });
fn main() {
let s = Status::Running;
println!("{:?}", s);
}
巨集的侷限
- 語法脆弱、錯誤訊息不直觀
- 進階功能(如烹調 AST)需要 procedure macro(proc macro,另一套 API)
- 過度使用會降低可讀性
原則:解決重複的平凡模式時用巨集,複雜規則用 proc macro 或函式。
練習
// 1. 寫一個 make_getters! 巨集,為 struct 生成對每個欄位的 getter
// 2. 寫一個 variadic 巨集 sum_all! 接受 0..n 個數相加
思考:怎樣的程式碼適合用巨集重構?有沒有其實用函式就夠了?
自我檢查
- 認識 fragment types
- 能寫生成 enum / 重複模式的巨集
- 知道巨集的侷限
- 判斷何時該用巨集
深入連結
- The Book 第 19 章+「The Little Book of Rust Macros」