【Rust】类函数宏 | Rust宏入门
本笔记总结自
我对其中的案例有所简化
bilibili不支持markdown是真的难顶
概述
宏的种类
Attributes
内置宏 built-in
过程宏 proc-macro
派生宏 derive
函数式的宏
AKA 类函数宏
macro_rules!
宏的变种,一般只考虑macro_rules!这一个宏
宏展开
很像 C 的 Define,在编译时自动替换
rust 中的宏是在 AST 之后展开,自己会加括号,不会改变运算顺序
卫生性
hygiene 一个概念,简单理解为:宏不应该隐式地改变或创建变量
比如一个宏,用户没有传入变量a,但它把a的值改变了;或者它创建了变量b,但始终没有move或drop,就不卫生
调试
rustc +nightly -Zunpretty=expanded hello.rs
思路
基本语法
expansion 也可以叫做 transcriber
matcher
匹配()或胡言乱语
匹配元变量
该例中,matcher为 $($elem: expr),*
元变量

有一个特殊的元变量叫做 $crate ,它用来指代当前 crate 。
小例子:
反复
repetition
语法:
$(...) sep rep
其中:
$: a token (token意为标记)
(...): the matcher which need repetition
sep: an optional separator token; example:,;
rep:?appear zero or one time*appear any times+appear once or more
Example:
多个变量的情况:
macro metavariable expressions
Unstable now (2023.3.27) and we can not use it in a stable channel
实战
斐波纳切数列

构建步骤
确定调用形式
确定想要生成的代码
改善调用形式
初步构建
替换
测试
导出
确定调用形式
据此,初步构建宏:
依次匹配:
字面量:
a[n] =一个及以上的表达式(expr)
字面量:
, ... ,一个表达式(expr),本例中,此为通式
确定想要生成的代码
改善调用形式
在 coding 的过程中发现,用户可能需要能够自定义迭代器中Item的类型
故修改宏的调用形式为:
据此初步构建宏:
初步构建
将前面几个步骤的结果组合在一起
cargo test
这是由于在某次版本更新后, expr 之后只能跟随 =>、,、; 之一
故解决方法为用 ;...; 代替 ,..., ,修改以下两行:
当前完整代码:
替换
完成后:
cargo test
据说在 nightly 版本中,可以变异通过。此处不通过的原因在于,测试中的 a 和 n 与宏中的 a 和 n 具有不同的上下文,解决方法是:
这样,rustc 才能推断出 a 和 n 是 ident(identifier)
其他测试
导出宏
完整代码

