Files
rust/Macro/readme.md
2025-10-05 23:51:24 +08:00

125 lines
2.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

完全可以,我们来系统讲一下 `macro_rules!`**宏变量匹配类型**,也就是你说的除了 `expr` 还能匹配什么。
---
## 1⃣ 基本宏变量语法
```rust
$变量名:匹配类型
```
* `$` → 宏变量前缀
* `变量名` → 自己命名
* `匹配类型` → Rust 定义的一些匹配规则,告诉宏要匹配什么类型的语法单元
---
## 2⃣ 常用匹配类型
| 匹配类型 | 描述 | 示例 |
| --------- | --------------- | --------------------------------------- |
| `expr` | 表达式 | `5 + 3`, `a * b`, `func(1)` |
| `ident` | 标识符 | `x`, `my_var` |
| `ty` | 类型 | `i32`, `Vec<String>` |
| `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<i32> = make_default!(Vec<i32>);
```
#### 标识符匹配
```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` 的对应语法单元和示例都标出来,一目了然。
你希望我画吗?