【发布时间】:2016-11-02 06:42:19
【问题描述】:
假设我想在编译时替换所有出现的过程,例如用???? 替换所有出现的cons。我尝试了两个看起来很自然的选择:
1.
(define-syntax ????
(syntax-rules ()
[(_ x y) (cons x y)]))
如果我执行(???? 2 3) 之类的操作,这将有效,但如果???? 不在应用程序位置,我将无法使用它,所以如果我执行(map ???? '(1 2) '(3 4)),我会收到“语法错误”错误。
然后我想只是替换标识符本身:
2.
(define-syntax ????
(λ (_) #'cons))
现在???? 本身给了我#<procedure:cons> 和(map ???? '(1 2) '(3 4)) 给出了正确的答案,但是对于(???? 2 3),语法转换器正在接受所有参数并将整个表达式替换为cons,这不是什么我想要。
我如何实现我想要的?有没有某种变压器可以做到这一点?
更新:当我输入最后一句话时,我调用了“橡皮鸭效应”并找到了我想要的 make-rename-transformer。但是,文档说“可以手动编写这样的转换器”,而且我的 2 次尝试似乎都没有这样做。 如何手动制作这样的转换器?(忽略文档中make-syntax-transformer 的要点)
另外,我知道我可以只使用(define ???? cons),但那是运行时的一个额外的函数调用。
【问题讨论】:
-
使用
(define new-var old-var),您不会在运行时引入任何操作。您只是定义了相同的值具有两个不同的名称,并且您可以同时使用它们而不会导致任何低效率(您只是使您的代码更难阅读)。所以如果old-var是一个函数,调用(new-var arguments)就相当于调用(old-var arguments),没有任何额外的函数调用。 -
“这是运行时的额外函数调用”。并不真地。两个绑定都指向同一个函数,所以它不像
(define (de a d) (cons a d))