我最近一直在学习Scheme,并遇到了一个以下列方式定义的函数:
(define remove!
(let ((null? null?)
(cdr cdr)
(eq? eq?))
(lambda ... function that uses null?, cdr, eq? ...)
绑定null的目的是什么?为空?或cdr到cdr,当这些函数内置在没有let块的函数定义中可用的函数时?
答案 0 :(得分:30)
在普通R5RS方案中,没有模块系统 - 只有顶层。此外,心态是可以修改所有内容,因此您可以按照自己的方式“自定义”语言。但是没有模块系统,这种方法效果不佳。例如,我写
(define (sub1 x) (- x 1))
在您加载的库中 - 现在您可以重新定义-
:
(define - +) ; either this
(set! - +) ; or this
现在你无意中破坏了我的库,它依赖于sub1
将其输入减少一个,因此当你向下拖动它们时,你的窗口会上升,或者其他什么。
有几个库使用的唯一方法就是“抓住”减法函数的相关定义,然后才能修改它:
(define sub1 (let ((- -)) (lambda (x) (- x 1))))
现在事情会更“正常”,因为您无法通过更改sub1
来修改-
功能的含义。 (除非......如果您在加载我的库之前修改它...)
无论如何,由于这个原因(如果您知道加载库时-
是原始的),一些编译器会检测到这一点并看到-
调用总是将成为实际的减法函数,因此它们将内联调用(并且内联调用-
最终会导致汇编代码减去两个数字,因此这是一个很大的速度提升)。但就像我在上面的评论中所说的那样,这更像是上面的实际原因。
最后,R6RS(以及之前的几个方案实现)已修复此问题并添加了一个库系统,因此这个技巧没有用处:sub1
代码是安全的,只要其库中的其他代码不是以某种方式重新定义-
,编译器可以基于此安全地优化代码。不需要聪明的技巧。
答案 1 :(得分:2)
这是速度优化。局部变量访问通常比全局变量更快。