「这是我参与11月更文挑战的第 21 天,活动详情查看:2021最后一次更文挑战」
在 Rust 众多有趣的功能特性中,Rust 宏无疑是最有趣的那个(个人觉得)。可惜的是,即使读完了这本书和各种教程,然后我试图实现一个处理不同元素的复杂列表的宏时,我仍然很难理解它应该如何做。花了一些时间,直到我到了那个 “叮” 的时刻,开始错误地使用宏来处理一切:) (好吧,不是像我所看到的那样,在所有的事情上都使用宏,因为我不想使用函数和指定类型和生命期,但在任何地方都是有用的)
因此,这里是我对描述编写此类宏背后的原则的看法。它假定你已经阅读了 书中的宏部分,并且熟悉基本的宏定义和标记类型。
在本教程中,我将以逆波兰表达式为例。它很有趣,因为它足够简单,你可能已经从学校熟悉了它,然而为了在编译时静态地实现它,你已经需要使用递归宏的方法。
逆波兰表达式(也叫后缀记数法)使用栈进行所有操作,因此任何操作数都被推到栈中,任何[二进制]运算符都从栈中取出两个操作数,评估结果并将其放回。因此,像下面这样的表达式:
1 | rust复制代码2 3 + 4 * |
翻译为:
- 把2放到栈里
- 把3放进栈里
- 从堆=栈中取出最后两个值(3和2),应用运算符+,将结果(5)放回栈中
- 把4放到栈中
- 从堆栈中取出最后两个值(4和5),应用运算符*(4*5),将结果(20)放回堆栈中
- 表达式结束,堆栈中的单个值就是结果(20)
在数学和大多数现代编程语言中使用的更常见的infix符号中,表达式看起来像 (2+3)*4
。
所以让我们写一个宏,在编译时评估RPN,将其转换为Rust所理解的infix符号:
1 | rust复制代码macro_rules! rpn { |
让我们从将数字推入栈开始。
本文转载自: 掘金