emacs lisp 中 lambda 的格式
我正在尝试在 emacs lisp 中应用闭包。我在这里找到了一篇文章: 在 Emacs Lisp 中执行闭包?
(defun foo (x) `(lambda () ,x)) (消息 (字符串 (funcall (foo 66))))
但是遵循emacs 文档 lambda 的格式应类似于 '(lambda()x)==>使用这种格式,我得到一个错误:符号作为变量的值是void:x
当“,”在“()”和“x”之间添加时,一切正常。
为什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
发生这种情况是因为 Emacs Lisp 是动态作用域的,因此
foo
返回一个 lambda,其中x
是空闲的。这就是错误告诉你的。要在 Emacs Lisp 中执行闭包,您必须使用 lexical-let 来模拟词法绑定,从而允许您创建真正的闭包。
以下是来自 Emacs Wiki 的一些链接:
请注意,您可以定义
x
带有像这样的let:This happens because Emacs Lisp is dynamically scoped thus
foo
returns a lambda wherex
is free. That's what the error tells you.To do a closure in Emacs Lisp you have to use
lexical-let
which simulates a lexical binding and therefore allows you to make a real closure.Here are some links from the Emacs Wiki:
Note that you could have defined
x
with a let like this:这个答案提供了 @Daimrod 正确答案第一部分背后的一些细节。
你的问题是为什么这有效:
而这不起作用:
首先,第二个引号(
'
)是不必要的,因为在 Emacs Lisp 中 lambda 形式是 self-评估。也就是说,'(lambda (...) ...)
通常与(lambda (...) ...)
的行为相同。但是反引号 (
`
) 代替引号 ('
) 的作用是什么?在反引号表达式中,逗号 (
,
) 表示将下一个表达式替换为其值,即对其求值。所以这:意味着创建并返回一个列表,其第一个元素是符号
lambda
(未求值),第二个元素是()
(未求值),其第三个元素是变量x
的值。它相当于评估此代码,该代码使用函数list
:这就是您想要的:用当前值(在本例中为它的当前值)替换 x函数
foo
内的值,即foo
参数的值)。但是这个:(
同样,因为 lambda 形式是自求值,
(lambda () x)
)返回此列表:(lambda () x)
。当使用动态作用域(Emacs Lisp 中的默认作用域机制)对其进行评估时,x
是未绑定的 - 它没有任何值。因此会引发 void-variable 错误。This answer gives a bit of detail behind the first part of @Daimrod's correct answer.
Your question is why this works:
and this doesn't work:
First, the quote (
'
) is unnecessary in the second, because in Emacs Lisp lambda forms are self-evaluating. That is,'(lambda (...) ...)
generally acts the same as(lambda (...) ...)
.But what does the backquote (
`
), instead of quote ('
), do?Inside a backquoted expression, a comma (
,
) means replace the next expression by its value, that is, evaluate it. So this:means create and return a list whose first element is the symbol
lambda
(that's not evaluated), whose second element is()
(that's not evaluated), and whose third element is the value of variablex
. It's equivalent to evaluating this code, which uses functionlist
:That's what you want: replace
x
by its current value (in this case, its value inside the functionfoo
, that is, the value offoo
's argument).But this:
(and likewise, because a lambda form is self-evaluating,
(lambda () x)
) returns this list:(lambda () x)
. And when that's evaluated using dynamic scoping (the default scoping regime in Emacs Lisp),x
is unbound - it has no value. So a void-variable error is raised.