不久前,我在Scheme中编写了一个程序,该程序将使用宏来发展L系统。本质上,存在关于令牌如何扩展的规则,这些规则将以递归方式运行。例如,给定规则:
F => F F
X => X < F > F
> => identity (stay >)
< => identity (stay <)
如果我们以X
开头,则会得到:
// after 0 iterations
X
// after 1 iteration
X < F > F
// after 2 iterations
X < F > F < F F > F F
// after 3 iterations
X < F > F < F F > F F < F F F F > F F F F
等等。在Scheme中,这是一种魅力。超级简单的匹配和递归宏定义。呼叫看起来像这样:
; macro name iters starting tokens
(evolve-lsys-n 5 X F X)
但是我真的很难用Rust做到这一点。
标准macro_rules!
具有模式匹配的优势,这非常好。但不幸的是,据我所知,并没有取消引用/准引用,因此我实际上无法进行尾递归(我认为?)
程序宏似乎是一种解决方法,但是我也为如何做到这一点而苦苦挣扎。
如果输入的内容与我在Scheme(evolve!(X F X)
)中输入的内容相同,我该如何实际遍历这些令牌?
随着rust的功能越来越强大,我也希望我可以在不增加空格的情况下获得更具表现力的输入。例如,evolve!(XFX)
会很好。这可能吗?这似乎没有什么好处,但是在定义扩展规则时,它们实际上可能会变得很大,因此避免空格会很好。
最后,在方案I中,还能够实现参数宏。这意味着某些“令牌”将具有参数。调用看起来像这样:evolve!(X F(10) X)
,而F(10)
的扩展将采用参数并对其进行处理,例如F(t) F(t * 2)
,以便F(10)
会扩展到F(10) F(20)
。
很明显,我无需宏即可完成所有这些工作。我真的很喜欢为所有这些使用宏的想法,因为这只是一个有趣的练习,而源于“定义自己的语法”的思想,这对我来说是Scheme和类似Lisp语言最吸引人的部分。 >
谢谢