了解 LISP 中的 "let" 表达式
Understanding "let" expression in LISP
我对 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)
原因是您使用的是带有 dynamic binding 的 Lisp 方言(link Emacs Lisp 文档对此有很好的描述)。
详细地说,您的程序的行为方式是因为 let
表达式为 x
创建的新绑定在 [=13= 时取代了 (defvar x 1)
] 从 let
表达式中调用。因此,g
函数不是将 1 添加到它的参数,而是添加 x
的当前值,当在 let
表达式中时该值是 5。
因为你使用了(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 非常陌生,以前有过函数式编程的经验(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)
原因是您使用的是带有 dynamic binding 的 Lisp 方言(link Emacs Lisp 文档对此有很好的描述)。
详细地说,您的程序的行为方式是因为 let
表达式为 x
创建的新绑定在 [=13= 时取代了 (defvar x 1)
] 从 let
表达式中调用。因此,g
函数不是将 1 添加到它的参数,而是添加 x
的当前值,当在 let
表达式中时该值是 5。
因为你使用了(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