本页目录
声明宏 (macro_rules!)
macro_rules!用模式匹配+重复来定义宏——$($x:expr),*表示零或多个用逗号分隔的表达式。fragment specifiers(expr/ty/ident/tt)限制匹配的语法片段类型,tt muncher 是实现变参宏的高级技巧。声明宏和函数的区别:宏在编译期展开为 AST 节点,函数在运行时被调用——宏可以做到函数做不到的语法级抽象。
macro_rules! 不是函数
宏和函数的根本区别:宏在编译期展开为代码(不是运行时调用)。这意味着宏可以接受变长参数、可以产生不同类型的代码、可以生成标识符——这些都是函数做不到的。
Fragment Specifiers: 宏的"类型系统"
| specifier | 匹配 | 示例 |
|---|---|---|
:expr | 任意表达式 | 42, x + y, { ... } |
:ident | 标识符 | my_var, HashMap |
:ty | 类型 | i32, Vec<String> |
:tt | 任意 token tree | 最通用,用于构建高级宏 |
: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) |
重复模式
$,* $? # 可选的尾随逗号
*: 零次或多次+: 一次或多次?: 零次或一次(可选)
tt Muncher: 递归处理 token 树
最强大的宏模式——用递归和 :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: Chapter 19.5 — Macros
Keywords: macro_rules!, declarative macro, repetition, tt muncher, fragment specifier, compile-time expansion