理解 LISP 中的“let”表达式
Posted
技术标签:
【中文标题】理解 LISP 中的“let”表达式【英文标题】:Understanding "let" expression in LISP 【发布时间】: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)
【问题讨论】:
【参考方案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
【讨论】:
以上是关于理解 LISP 中的“let”表达式的主要内容,如果未能解决你的问题,请参考以下文章