rustp-42.宏
Rust中的宏
-
Rust中的宏主要有两种,一种是使用macro_rules!的声明宏,一种是过程宏,过程宏又
分成三种:
(1) 自定义宏#[derive],在结构体、枚举等上指定通过derive属性添加代码
(2) 类属性宏,定义可以用于任意项的自定义属性
(3) 类函数宏,看起来像是函数,但是作用于作为参数传递的Token -
宏和函数
(1) 宏是一种为写其他代码而写代码的方式,对于减少大量编写代码和维护代码非常有用
(2) 一个函数标签必须声明函数参数的个数和类型,宏只接受可变参数
(3) 宏的定义比函数定义更加复杂
(4) 调用宏之前,必须定义并且将其引入作用域,函数但是可以在任何地方调用和定义
声明宏
rust
1 | let v = vec![1,2,3]; |
创建自己的声明宏
bash
1 | mkdir learn |
- 之后,进行设置
rust
1 | //learn/Cargo.toml |
- 创建mac lib
bash
1 | cargo new mac --lib |
- 设置mac lib
rust
1 |
|
- 创建main
bash
1 | # /learn |
- 修改main
rust
1 | [dependencies] |
- 写主函数
bash
1 | vim src/main.rs |
rust
1 | # learn/main/src/main.rs |
过程宏
过程宏接受Rust代码作为输入,在代码上操作,产生另一些代码作为输出,非像声明宏那样
匹配对应的模式,然后以另一部分代码替换当前代码
定义过程宏函数接受一个TokenStream作为输入并产生一个TokenStream作为输出,也就是宏
的核心,宏所处理的源代码组成了输入TokenStream,同时宏生成的代码是输出TokenStream,
如下:
rust
1 | use proc_macro; |
自定义derive宏
名称必须为some some_derive这种,与例子相同
- 首先创建hello_macro
bash
1 | cargo new hello_macro --lib |
- 之后进行编辑
rust
1 | pub trait HelloMacro { |
- 之后在这个文件夹中新建
bash
1 | # 位置:hello_macro/ |
- 填写:
rust
1 | [lib] |
- 实现代码填写
rust
1 | extern crate proc_macro; |
- 使用宏的代码
bash
1 | cd .. |
- 编写依赖
rust
1 | [dependencies] |
- 编写代码
rust
1 | //main/src/main.rs |
类属性宏
类属性宏和derive宏类似,但是不同于为derive属性生成代码,允许创建新的属性,通过接受输入的
标记替换为新的标记,派生宏则是接受输入的TokenTree,然后追加新的标记树
- 例子:
创建一个名为route的属性用于注解web应用程序框架(web application framework)的函数:
rust
1 |
|
(1) route属性将由框架本身定义为一个过程宏,宏定义签名函数:
rust
1 |
|
属性宏接受两个参数,一个是attr,类似#[allow(unused)]
中的unused,另一个是item,是被属性
修饰的item,如结构体的定义
(2) 类属性工作宏和自定义derive宏工作方式相同