如何比较球拍中的语法对象?

JRR*_*JRR 7 racket

我想比较两个语法对象的代码内容并忽略上下文等内容。将它们转换为数据是唯一的方法吗?喜欢:

(equal? (syntax->datum #'(x+1)) (syntax->datum #'(x+1)))
Run Code Online (Sandbox Code Playgroud)

Lei*_*sen 7

如果您想比较两个对象而不解构它们,那么可以。

然而,此方法的问题在于,它仅比较附加到两个语法对象的数据,而不会实际比较它们的绑定信息。

我(来自Ryan Culpepper )听到的类比是,这有点像拿两幅画,沥干它们的颜色,然后看看它们是否相同。虽然它们在某些方面可能相似,但您会错过不同颜色的很多差异。

更好的方法(尽管它确实需要一些工作)是使用将syntax-e语法对象解构为更原始的语法对象列表,并执行此操作直到获得标识符(基本上是其数据是符号的语法对象),从那里,您通常可以使用free-identifier=?( 有时bound-identifier=?可以查看每个标识符是否可以相互绑定,并identifier-binding比较模块级别标识符。

之所以没有一个简单的谓词来比较两个任意语法对象,是因为一般来说,对于使两段代码相等的原因并没有一个很好的定义,即使您只关心语法相等性。例如,使用上面引用的函数不会跟踪语法对象中的内部绑定,因此您仍然会得到“相等”含义的非常严格的定义。也就是说,两个语法对象具有相同的结构,其标识符要么绑定到同一模块,要么是free-identifier=?.

因此,在您使用这个答案之前,我强烈建议您退一步并确保这确实是您想要做的。这是千载难逢的事,但大多数时候你实际上是在尝试解决类似但更简单的问题。