【问题标题】:Understanding "let" expression in LISP理解 LISP 中的“let”表达式
【发布时间】:2015-07-26 14:55:01
【问题描述】:

我对 lisp 非常陌生,之前有过函数式编程(Haskell,SML)的经验。为什么这段代码返回14,而不是10(即1 + 2y + 3 + 1)?

(defvar x 1)

(defun g (z)
  (+ x z))

(defun f (y)
  (+ (g 1)
     (let ((x (+ y 3)))
        (g (+ y x)))))

(f 2)

【问题讨论】:

    标签: lisp common-lisp let


    【解决方案1】:

    原因是您使用的是带有 dynamic binding 的 Lisp 方言(Emacs Lisp 文档中对此有很好描述的链接)。

    详细地说,您的程序的行为方式是因为当从 let 表达式中调用 g 时,由 let 表达式创建的 x 的新绑定取代了 (defvar x 1) .因此,g 函数不是将 1 添加到其参数,而是将 x 的当前值添加到 let 表达式中时为 5。

    【讨论】:

    • 你怎么知道这是elisp?这也是有效的 common-lisp。
    • @Sylwester:我不知道它是 elisp,但这是我发现的第一个文档页面,它简洁地解释了动态绑定。
    【解决方案2】:

    因为您使用了(DEFVAR X 1),它将X 声明为全局特殊变量。然后,这会导致 X 的所有其他后续绑定使用动态绑定:在 (LET ((X ... 中。

    Lisp 中的样式和约定

    Lisp 中的约定:对特殊变量使用 *X* 而不是 X

    (defvar *x* 1)
    

    那么你的代码是:

    (defvar *x* 1)   ; global special variable *X*
    
    (defun g (z)
      (+ *x* z))     ; use special variable *X*
    
    (defun f (y)
      (+ (g 1)
         (let ((x (+ y 3)))    ; lexical binding of X
            (g (+ y x)))))     ; use lexical binding of X
    

    运行:

    ? (f 2)
    10
    

    【讨论】:

      猜你喜欢
      • 2019-01-29
      • 2014-11-28
      • 2010-10-07
      • 2014-01-01
      • 2018-06-24
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 1970-01-01
      相关资源
      最近更新 更多