繁体   English   中英

为什么Common Lisp中的闭包没有捕获封闭函数的参数?

[英]Why are arguments to an enclosing function not captured by closures in Common Lisp?

test.lisp

(defvar test
  #'(lambda (var1)
      #'(lambda (var2)
          `((var1 . ,var1)
            (var2 . ,var2)))))
(defvar var1 'wrong)
(defvar var2 'wrong)

在REPL中:

$ clisp -q -i test.lisp
;; Loading file test.lisp ...
;; Loaded file test.lisp
[1]> (funcall (funcall test 'right) 'right)
((VAR1 . WRONG) (VAR2 . RIGHT))

我认为普通的lisp这些天应该是词法范围的,所以为什么var1的值在test没有被内部lambda捕获? 我如何确保它被捕获?

使用解释器时可以看到这一点。

我们先来看看编译器:

? (load "/tmp/test.lisp")
#P"/private/tmp/test.lisp"
? (funcall (funcall test 'right) 'right)
((VAR1 . RIGHT) (VAR2 . RIGHT))

首先,函数正在编译。 编译器假定词法绑定。 然后DEFVAR声明变量VAR1VAR2是特殊的( - >不是词法)。 在执行的代码中,代码仍然使用词法绑定。

您使用的是口译员:

首先加载函数。 什么都没有编译。 然后DEFVAR VAR1VAR2声明为特殊。

在执行的代码中,解释器正在使用动态绑定 - 就像您声明的那样。 解释器在运行时查看变量,并看到它们被声明为特殊的。

差异

编译器在特殊声明之前生成了机器代码。 因此在运行时它使用词法绑定。

解释器在现有声明中查看运行时。

样式

如果要避免动态绑定,请不要将变量声明为特殊变量。

defvar (和defparameter )将变量声明为特殊(动态)。 给你的特殊变量*earmuffs*以防止关于绑定是词汇还是动态的惊喜。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM