emacs lisp 中 lambda 的格式

发布于 2024-12-22 17:48:44 字数 570 浏览 2 评论 0 原文

我正在尝试在 emacs lisp 中应用闭包。我在这里找到了一篇文章: 在 Emacs Lisp 中执行闭包?

如何使用一些代码 喜欢:

(defun foo (x) `(lambda () ,x)) (消息 (字符串 (funcall (foo 66))))

但是遵循emacs 文档 lambda 的格式应类似于 '(lambda()x)==>使用这种格式,我得到一个错误:符号作为变量的值是void:x

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

为什么?

I'm tring to apply closure in emacs lisp.And I find a post here:
How do I do closures in Emacs Lisp?

with some code like:

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

But following the emacs documentation lambda should be formated like
'(lambda () x) ==> using this format ,I got an ERROR :Symbol's value as variable is void: x

When " , " is add betwenn "()" and "x" ,everything goes right .

Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你的背包 2024-12-29 17:48:44

发生这种情况是因为 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 带有像这样的let:

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

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

This happens because Emacs Lisp is dynamically scoped thus foo returns a lambda where x 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.

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

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

Here are some links from the Emacs Wiki:

  1. Dynamic Binding Vs Lexical Binding
  2. Fake Closures

Note that you could have defined x with a let like this:

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

(message (string (let ((x 66)) (funcall 
                                (foo 'i-dont-care)))))
瘫痪情歌 2024-12-29 17:48:44

这个答案提供了 @Daimrod 正确答案第一部分背后的一些细节。

你的问题是为什么这有效:

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

而这不起作用:

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

首先,第二个引号(')是不必要的,因为在 Emacs Lisp 中 lambda 形式是 self-评估。也就是说,'(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 错误。

This answer gives a bit of detail behind the first part of @Daimrod's correct answer.

Your question is why this works:

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

and this doesn't work:

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

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:

`(lambda () ,x)

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 variable x. It's equivalent to evaluating this code, which uses function list:

(list 'lambda '() x)

That's what you want: replace x by its current value (in this case, its value inside the function foo, that is, the value of foo's argument).

But this:

'(lambda () x)

(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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文