「用 macro! 实现逆波兰表达式」开始

「这是我参与11月更文挑战的第 21 天,活动详情查看:2021最后一次更文挑战


在 Rust 众多有趣的功能特性中,Rust 宏无疑是最有趣的那个(个人觉得)。可惜的是,即使读完了这本书和各种教程,然后我试图实现一个处理不同元素的复杂列表的宏时,我仍然很难理解它应该如何做。花了一些时间,直到我到了那个 “叮” 的时刻,开始错误地使用宏来处理一切:) (好吧,不是像我所看到的那样,在所有的事情上都使用宏,因为我不想使用函数和指定类型和生命期,但在任何地方都是有用的)

因此,这里是我对描述编写此类宏背后的原则的看法。它假定你已经阅读了 书中的宏部分,并且熟悉基本的宏定义和标记类型。

在本教程中,我将以逆波兰表达式为例。它很有趣,因为它足够简单,你可能已经从学校熟悉了它,然而为了在编译时静态地实现它,你已经需要使用递归宏的方法。

逆波兰表达式(也叫后缀记数法)使用栈进行所有操作,因此任何操作数都被推到栈中,任何[二进制]运算符都从栈中取出两个操作数,评估结果并将其放回。因此,像下面这样的表达式:

1
rust复制代码2 3 + 4 *

翻译为:

  1. 把2放到栈里
  2. 把3放进栈里
  3. 从堆=栈中取出最后两个值(3和2),应用运算符+,将结果(5)放回栈中
  4. 把4放到栈中
  5. 从堆栈中取出最后两个值(4和5),应用运算符*(4*5),将结果(20)放回堆栈中
  6. 表达式结束,堆栈中的单个值就是结果(20)

在数学和大多数现代编程语言中使用的更常见的infix符号中,表达式看起来像 (2+3)*4

所以让我们写一个宏,在编译时评估RPN,将其转换为Rust所理解的infix符号:

1
2
3
4
5
rust复制代码macro_rules! rpn {
// TODO
}

println!("{}", rpn!(2 3 + 4 *)); // 20

让我们从将数字推入栈开始。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%