【问题标题】:In Scheme the purpose of (let ((cdr cdr))在 Scheme 中 (let ((cdr cdr)) 的目的
【发布时间】:2010-07-09 14:37:01
【问题描述】:

我最近一直在研究Scheme,遇到了一个按以下方式定义的函数:

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

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

【问题讨论】:

    标签: scheme


    【解决方案1】:

    在普通的 R5RS 方案中,没有模块系统——只有顶层。此外,心态是一切都可以修改,所以你可以“定制”任何你想要的语言。但是如果没有模块系统,这将无法正常工作。比如我写

    (define (sub1 x) (- x 1))
    

    在您加载的库中——现在您可以重新定义-

    (define - +) ; either this
    (set! - +)   ; or this
    

    现在您无意中破坏了我的库,该库依赖于 sub1 将其输入减一,因此当您将它们向下拖动时,您的窗口会上升,或者其他什么。

    几个库都在使用的唯一方法是在有人修改之前“获取”减法函数的相关定义:

    (define sub1 (let ((- -)) (lambda (x) (- x 1))))
    

    现在事情会“更顺利”,因为您无法通过更改- 来修改我的sub1 函数的含义。 (除了......如果你修改它之前你加载我的图书馆......)

    无论如何,由于这个原因(如果你知道 - 是加载库时的原始值),一些编译器会检测到这一点并看到 - 调用总是实际的减法函数,因此它们将内联调用它(并且内联对 - 的调用最终会导致汇编代码减去两个数字,因此这是一个很大的速度提升)。但就像我在上面评论中所说的,这与上面的实际原因更加巧合。

    最后,R6RS(以及之前的几个方案实现)已经修复了这个问题并添加了一个库系统,所以这个技巧没有用处:sub1 代码是安全的,只要它的库中的其他代码没有重新定义 @ 987654332@ 以某种方式,编译器可以基于此安全地优化代码。不需要聪明的技巧。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 你能详细解释一下吗?与 let 绑定的过程似乎与查找所需的时间一样多。
      • @redwoolf:与let 绑定时的查找只发生一次,但cdr 可能会在函数中被多次使用(并查找)。
      • 虽然这在某些实现中可以带来速度优势,但它只是这样做的更重要原因的副产品。我将在单独的答案中写到这一点。
      猜你喜欢
      • 1970-01-01
      • 2020-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多