emacs lisp中lambda的格式。

问题描述 投票:1回答:1

我想在Emacs Lisp中应用闭包,在这里找到了一个帖子。如何在Emacs Lisp中做闭包?

有一些代码,比如

(defun foo (x) `(lambda () ,x)) (message (string (funcall (foo 66)))

但按照emacs 文件 lambda的格式应该是'(lambda () x) ==> 使用这种格式,我得到了一个错误:符号的值作为变量是void: x。

当在"() "和 "x "之间加上", "时,一切都正常了。

为什么呢?

lambda emacs closures lisp lexical-scope
1个回答
3
投票

这种情况的发生是因为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中的一些链接。

  1. 动态绑定与词法绑定的比较
  2. 伪装封条

请注意,您可以定义 x 与这样的让。

(defun foo (x)
  (lambda () x))

(message (string (let ((x 66)) (funcall 
                                (foo 'i-dont-care)))))

0
投票

这个答案给出了 @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错误。

© www.soinside.com 2019 - 2024. All rights reserved.