什么时候在Common Lisp中创建局部变量?

问题描述

是在defun表单求值期间还是在函数应用程序期间创建了局部变量?

解决方法

binding 是比“变量”更有用的术语,它是名称和值之间的关联。变量是Common Lisp中的一种绑定:还有其他绑定。

对于诸如

的功能
(defun foo (x)
  (let ((y (+ x 2)))
    (+ y x)))

然后以(foo (+ 2 1))之类的格式显示:

  • 首先评估(+ 2 1)并将其结果3绑定到函数中的x
  • 然后使用上面的(+ x 2)绑定对x进行求值,其结果5y形式绑定到let
  • 最后,(+ y x)是通过上面的两个绑定求值的,其结果8是函数调用的返回值。

请注意,在其他条件相同的情况下,只要有可能进行引用,便可以从建立绑定开始就对其进行访问:它们具有无限的范围。上面的内容无关紧要,因为函数返回后没有引用的可能性。像

这样的函数确实很重要
(defun bar (x)
  (lambda (y)
    (+ x y)))

由于调用bar返回的函数引用了其绑定x,因此只要该函数继续存在,该绑定就必须继续存在。在绑定发生突变的情况下,很容易看出这一点必须成立:

(defun bar (x)
  (lambda (y)
    (+ y (incf x))))

然后

> (let ((f (bar 0)))
    (values (funcall f 1) (funcall f 1)))
2
3

这里还有其他各种情况。