emacs lisp中的lambda格式

时间:2011-12-23 09:00:13

标签: emacs lambda lisp closures

我想在emacs lisp中应用闭包。我在这里找到一个帖子: How do I do closures in Emacs Lisp?

使用一些代码:

  

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

但是跟随emacs documentation lambda应该像这样格式化 '(lambda()x)==>使用这种格式,我得到一个错误:符号的值作为变量是void:x

当“,”添加到“()”和“x”之间时,一切都正常。

为什么?

2 个答案:

答案 0 :(得分:3)

这是因为Emacs Lisp是动态范围的,因此foo返回x空闲的lambda。这就是错误告诉你的。

要在Emacs Lisp中执行闭包,您必须使用lexical-let来模拟词法绑定,因此允许您进行真正的闭包。

(defun foo (x)
  (lexical-let ((x x))
               (lambda () x)))

(message (string (funcall (foo 66))))

以下是Emacs Wiki的一些链接:

  1. Dynamic Binding Vs Lexical Binding
  2. Fake Closures
  3. 请注意,您可以使用以下内容定义x

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

答案 1 :(得分:0)

此答案在@Daimrod正确答案的第一部分后面提供了一些细节。

您的问题是为什么有效:

<body style="background-color: #aaa">
  <span id="red" style="color:red"> RED </span>
  <span id="blue" style="color:blue"> BLUE </span>
  <span id="lightblue" style="color:lightblue"> LIGHTBLUE </span>
  <span id="yellow" style="color:yellow"> YELLOW </span>
  <span id="purple" style="color:purple"> PURPLE </span>
  <span id="green" style="color:green"> GREEN </span>
</body>

这不起作用:

(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中的值,即{{1 }}的论点。

但这是

foo

(同样,由于Lambda形式是自评估的,因此foo)将返回以下列表:'(lambda () x) 。而且,如果使用动态范围(Emacs Lisp中的默认范围设置)对它进行评估,则(lambda () x)是不受约束的-它没有任何价值。因此会引发空变量错误。