このページの目次
宣言的マクロ (macro_rules!)
macro_rules!はパターンマッチングと反復を用いてマクロを定義します——$($x:expr),*は、カンマ区切りの式がゼロ個以上あることを表します。フラグメント指定子(expr/ty/ident/tt)はマッチする構文断片のタイプを制限し、tt muncher は可変引数マクロを実装するための高度なテクニックです。宣言的マクロと関数の違い:マクロはコンパイル時に AST ノードに展開され、関数は実行時に呼び出されます——マクロは関数ではできない構文レベルの抽象化を実現できます。
macro_rules! は関数ではない
マクロと関数の根本的な違い:マクロはコンパイル時にコードに展開されます(実行時の呼び出しではありません)。これは、マクロが可変長引数を受け取ったり、異なるタイプのコードを生成したり、識別子を生成したりできることを意味します。これらは関数では実現できません。
フラグメント指定子:マクロの「型システム」
| 指定子 | マッチ対象 | 例 |
|---|---|---|
:expr | 任意の式 | 42, x + y, { ... } |
:ident | 識別子 | my_var, HashMap |
:ty | 型 | i32, Vec<String> |
:tt | 任意のトークン木 | 最も汎用的で、高度なマクロの構築に使用 |
:literal | リテラル | 1, "hello", true |
:pat | パターン | Some(x), 1..=10 |
:path | パス | std::collections::HashMap |
:block | ブロック | { stmt1; stmt2; } |
:stmt | 文 | let x = 1;, x; |
:item | 項目 | fn f() {}, struct S; |
:meta | 属性の内容 | derive(Debug) |
反復パターン
$,* $? # 任意の末尾のコンマ
*: 0回以上+: 1回以上?: 0回または1回(任意)
tt Muncher: トークン木の再帰処理
最も強力なマクロパターン——再帰と :tt を用いて任意に複雑な入力を処理します:
let s = html!;
// → "<div>hello<span>world</span></div>"
tt muncher の原理:各マクロ呼び出しで <tag> ... </tag> パターンにマッチし、その後 $children を再帰的に展開します。これは proc macro を必要とせず、純粋な macro_rules! のみで実現可能です。
参考
- Little Book of Rust Macros: danielkeep.github.io/tlborm
- Rust Book: 第19章 5節 — マクロ
キーワード: macro_rules!, 宣言的マクロ, 反復, tt muncher, フラグメント指定子, コンパイル時展開