【问题标题】:Lisp evaluation of let statements对 let 语句的 Lisp 评估
【发布时间】:2010-10-13 18:23:23
【问题描述】:

我正在编写一个 Scheme 解释器,我遇到了一个有效的 let 语句,例如:

;; should print 7
(let ((a 4) (b 3))
    (let ((a (* a a)) 
          (b (* b b)))
       (+ a b)
       (- a b)))

我的解释器只实现了 Scheme 的一个纯函数子集,所以不会有 set! 之类的副作用。在纯粹的函数式语言中,为什么要在上面的 let 语句中允许多个表达式?

在编写我的解释器时,除了 let 中的最后一个表达式,我还有什么理由应该评估任何东西?似乎它们永远不会影响最后评估的语句的结果。

【问题讨论】:

    标签: lisp scheme interpreter


    【解决方案1】:

    实际上,除了最后一个语句之外,您不能“删除”所有语句,因为前面的语句可能是非终止的。例如:

    (define (func) (func))
    
    (let ()
      (func) ;; does not return
      1)
    

    如果您在此处未计算 (func),则会得到错误的结果(即 1),而您应该得到非终止计算。

    另一个问题是 call/cc (call-with-current-continuation) (是的,它属于功能子集)可用于从非尾计算中实际返回位置,例如:

    (call-with-current-continuation
      (lambda (ret)
        (let ()
          (ret 3)
          4)))
    

    这将返回 3 而不是 4。这仍然是纯粹的功能。

    注意顺便说一句 (let () x y z) 等同于单语句形式 (let () (begin x y z)) 所以真正的问题是你是否需要 begin :)

    【讨论】:

      【解决方案2】:

      你是对的(几乎):如果你正在实现 Scheme 的纯函数子集(即没有 set!set-car!set-cdr!),那么除了 let 中的最后一个表达式之外的任何表达式都会有它们的返回值被丢弃了,并且由于您保证不会产生副作用,因此默默地忽略它们没有危险。

      不过,有一种小情况需要考虑,那就是前面的表达式是defines:

      (let ((x 3))
        (define y 4)
        (+ x y))
      

      这既合法又实用。但是,有一些好消息 - 在块内(如 let),您必须将所有 defines 放在顶部。如,这不被视为合法方案:

      (let ((x 3))
        (+ 2 3)
        (define y 4)
        (+ x y))
      

      这意味着在评估一个块时,您所要做的就是扫描顶部的 defines 并将它们包装到等效的 letrec 表达式中,然后继续忽略除最后一个表达式之外的所有表达式(您可以然后返回)。

      编辑: antti.huima 对 call/cc 提出了很好的观点。如果你要在你的实现中包含延续,你真的不能对什么时候评估事情做出很多假设。

      【讨论】:

        【解决方案3】:

        好的,let 只是创建一个绑定,例如 define。没有什么可以改变像set! 这样的绑定变量。所以现在,想想你名字的范围是什么:你绑定到4的'(+ a b)the same as thea`的a是什么? (提示:没有。)

        这里真正的重点是,即使在这样的 hinky 情况下,您也需要正确行事:范围和绑定规则简单且定义明确,并且执行类似的操作,看起来令人困惑,只是他们的结果。这很方便,因为通过与 let 进行本地词法范围绑定,即使存在不正当的情况,您也可以编写更清晰的程序。

        更新 哦,我遗漏了一点。你是对的,(+ a b) 调用没有持久的影响,但是在一般情况下你不能假设这是真的,你不能通过单独检查程序文本来确定它是否是真的。 (考虑一下:那里可能有其他函数代替“+”。)但是,如果您认为在不评估各种 let 子句的情况下会得到正确的结果,那么您不明白它正在尝试做什么。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-24
          • 1970-01-01
          • 2012-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多