理解LISP中的“let”表达

时间:2015-05-14 20:24:48

标签: lisp common-lisp let

我是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)

2 个答案:

答案 0 :(得分:11)

因为您使用了(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

答案 1 :(得分:4)

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

详细地说,您的程序的行为与它的行为方式相同,因为x表达式创建的let的新绑定取代(defvar x 1)g的位置从let表达式中调用。因此,g函数不是在其参数中添加1,而是添加x的当前值,当在let表达式内时,该值为5。