完全可以,我们来系统讲一下 `macro_rules!` 中 **宏变量匹配类型**,也就是你说的除了 `expr` 还能匹配什么。 --- ## 1️⃣ 基本宏变量语法 ```rust $变量名:匹配类型 ``` * `$` → 宏变量前缀 * `变量名` → 自己命名 * `匹配类型` → Rust 定义的一些匹配规则,告诉宏要匹配什么类型的语法单元 --- ## 2️⃣ 常用匹配类型 | 匹配类型 | 描述 | 示例 | | --------- | --------------- | --------------------------------------- | | `expr` | 表达式 | `5 + 3`, `a * b`, `func(1)` | | `ident` | 标识符 | `x`, `my_var` | | `ty` | 类型 | `i32`, `Vec` | | `pat` | 模式 | `Some(x)`, `(a, b)` | | `stmt` | 语句 | `let x = 1;` | | `block` | 代码块 | `{ let x = 1; x+2 }` | | `meta` | 元属性 | `derive(Debug)` | | `tt` | Token Tree(最通用) | 单个标记或标记组,几乎可以匹配任何东西 | | `path` | 路径 | `std::io::Result`, `crate::module::Foo` | | `literal` | 字面量 | `"hello"`, `42`, `3.14` | --- ### 3️⃣ 示例 #### 表达式匹配 ```rust macro_rules! add { ($a:expr, $b:expr) => { $a + $b }; } let x = add!(1 + 2, 3 * 4); // 匹配复杂表达式 ``` #### 类型匹配 ```rust macro_rules! make_default { ($t:ty) => { <$t>::default() }; } let v: Vec = make_default!(Vec); ``` #### 标识符匹配 ```rust macro_rules! create_var { ($name:ident) => { let $name = 42; }; } create_var!(my_var); println!("{}", my_var); // 输出 42 ``` #### 语句匹配 ```rust macro_rules! repeat_stmt { ($s:stmt) => { $s $s }; } repeat_stmt!(println!("Hi");) // 会打印两次 Hi ``` #### 代码块匹配 ```rust macro_rules! run_block { ($b:block) => { println!("Before"); $b println!("After"); }; } run_block!({ println!("Inside"); }); ``` 输出: ``` Before Inside After ``` --- ### 4️⃣ 小结 * `expr` 只能匹配表达式 * Rust 宏提供了多种匹配类型(`ident`, `ty`, `pat`, `stmt`, `block`, `literal`, `tt` 等) * `tt` 最通用,但匹配后需要自己处理结构 > 可以理解为:**每个匹配类型限制了宏能匹配的语法单元**,避免写宏时乱匹配或产生歧义 --- 我可以画一张 **macro_rules! 匹配类型示意图**,把 `expr, ident, ty, pat, stmt, block, tt, literal` 的对应语法单元和示例都标出来,一目了然。 你希望我画吗?