New Rust
This commit is contained in:
124
Macro/readme.md
Normal file
124
Macro/readme.md
Normal file
@@ -0,0 +1,124 @@
|
||||
完全可以,我们来系统讲一下 `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` 的对应语法单元和示例都标出来,一目了然。
|
||||
|
||||
你希望我画吗?
|
||||
Reference in New Issue
Block a user