在Scheme中的目的(let((cdr cdr))

时间:2010-07-09 14:37:01

标签: scheme

我最近一直在学习Scheme,并遇到了一个以下列方式定义的函数:

(define remove! 
    (let ((null? null?)
          (cdr cdr)
          (eq? eq?))
     (lambda ... function that uses null?, cdr, eq? ...)

绑定null的目的是什么?为空?或cdr到cdr,当这些函数内置在没有let块的函数定义中可用的函数时?

2 个答案:

答案 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)

这是速度优化。局部变量访问通常比全局变量更快。