emacs lisp中lambda的格式



我试图在emacs lisp中应用闭包。我在这里找到了一个帖子:如何在Emacs Lisp中使用闭包?

加上如下代码:

(defun foo (x))' (lambda (),x)) (message (string (funcall (foo . x)66))))

但是在emacs文档之后,lambda的格式应该如下'(lambda () x) ==>使用此格式,我得到一个错误:符号的值作为变量是void: x

当在"()"one_answers"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的链接:

  1. 动态绑定Vs词法绑定
  2. <
  3. 假闭包/gh>

注意,您可以使用这样的let来定义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错误。

相关内容

最新更新