欢迎光临散文网 会员登陆 & 注册

【Rust】类函数宏 | Rust宏入门

2023-03-28 04:17 作者:Louis翔  | 我要投稿

本笔记总结自The Little Book of Rust Macros

我对其中的案例有所简化

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 版本中,可以变异通过。此处不通过的原因在于,测试中的 an 与宏中的 an 具有不同的上下文,解决方法是:

 

这样,rustc 才能推断出 anident(identifier)

其他测试

 

导出宏

 

完整代码

 


【Rust】类函数宏 | Rust宏入门的评论 (共 条)

分享到微博请遵守国家法律