我想在Emacs Lisp中应用闭包,在这里找到了一个帖子。如何在Emacs Lisp中做闭包?
有一些代码,比如
(defun foo (x) `(lambda () ,x)) (message (string (funcall (foo 66)))
但按照emacs 文件 lambda的格式应该是'(lambda () x) ==> 使用这种格式,我得到了一个错误:符号的值作为变量是void: x。
当在"() "和 "x "之间加上", "时,一切都正常了。
为什么呢?
这种情况的发生是因为Emacs Lisp是动态范围的,因此 foo
返回一个lambda,其中 x
是免费的。这就是错误告诉你的。
在 Emacs Lisp 中,你必须使用 lexical-let
它模拟了一个词法绑定,因此允许你做一个真正的闭合。
(defun foo (x)
(lexical-let ((x x))
(lambda () x)))
(message (string (funcall (foo 66))))
以下是Emacs Wiki中的一些链接。
请注意,您可以定义 x
与这样的让。
(defun foo (x)
(lambda () x))
(message (string (let ((x 66)) (funcall
(foo 'i-dont-care)))))
这个答案给出了 @Daimrod正确答案的第一部分的细节.
你的问题是 何以 这工作。
(defun foo (x) `(lambda () ,x)) (message (string (funcall (foo 66))))
而这个不行
(defun foo (x) '(lambda () x)) (message (string (funcall (foo 66))))
首先,引号('
)在第二种情况下是不必要的,因为在Emacs Lisp中,lambda形式是自评价的。 也就是说。'(lambda (...) ...)
一般来说 (lambda (...) ...)
.
但后面的引号是什么呢?`
),而不是引用('
), 做?
在一个反引号表达式中,逗号(,
)的意思是用它的值替换下一个表达式,也就是对它进行评估。 所以这个
`(lambda () ,x)
意思是创建并返回一个列表,其第一个元素是符号为 lambda
未评估),其第二个元素是 ()
(未被评估),其第三个元素是 价值 可变 x
. 相当于评估这段代码,它使用了函数 list
:
(list 'lambda '() x)
这是你想要的。替换 x
的当前值(在本例中,它在函数 foo
的值,即 foo
的说法)。)
但这。
'(lambda () x)
(同样,由于lambda形式是自洽的。(lambda () x)
)返回这个列表。(lambda () x)
. 当使用动态作用域(Emacs Lisp中的默认作用域制度)进行评估时。x
是未绑定的 - 它没有值。 所以会出现一个void-variable错误。