我是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)
答案 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。