emacs lisp中lambda的格式

emacs lisp中lambda的格式,emacs,lisp,eval,quote,backquote,Emacs,Lisp,Eval,Quote,Backquote,我尝试在emacs lisp中应用闭包。我在这里找到一篇帖子: 使用以下代码: (defun foo(x)`(lambda(),x))(message(string)(funcall)(foo (66)) 但是在emacs之后,lambda的格式应该如下 '(lambda()x)==>使用此格式,我得到一个错误:作为变量的符号值为void:x 当“,”是加在“()”和“x”之间时,一切都正常 为什么?之所以会发生这种情况,是因为Emacs Lisp是动态作用域,因此foo返回一个lambda,

我尝试在emacs lisp中应用闭包。我在这里找到一篇帖子:

使用以下代码:

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

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

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


为什么?

之所以会发生这种情况,是因为Emacs Lisp是动态作用域,因此
foo
返回一个lambda,其中
x
是免费的。这就是错误告诉你的

要在Emacs Lisp中进行闭包,必须使用
lexicallet
,它模拟词法绑定,因此允许进行真正的闭包

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

(message (string (funcall (foo 66))))
以下是来自Emacs Wiki的一些链接:

  • 请注意,您可以使用如下let定义
    x

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

    这个答案给出了@Daimrod正确答案第一部分后面的一些细节

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

    (defun foo(x)`(lambda(),x))(消息(字符串(funcall(foo 66)))
    
    但这不起作用:

    (defun foo(x)'(lambda()x))(消息(字符串(funcall(foo 66)))
    
    首先,引号(
    )在第二个中是不必要的,因为在Emacs Lisp中,lambda表单是自评估的。也就是说,
    (lambda(…)…)
    的作用通常与
    (lambda(…)…)
    相同

    但是反引号(
    `
    )代替引号(
    '
    ),做了什么

    在反引号表达式中,逗号(
    )表示用下一个表达式的值替换下一个表达式,即对其求值。因此:

    `(lambda(),x)
    
    表示创建并返回一个列表,其第一个元素是符号
    lambda
    (未计算),第二个元素是
    ()
    (未计算),第三个元素是变量
    x
    值。这相当于评估此代码,它使用函数
    list

    (列出'lambda'()x)
    
    这就是您想要的:用它的当前值替换
    x
    (在本例中,它在函数
    foo
    中的值,即
    foo
    的参数值)

    但这是:

    ”(lambda()x)
    

    (同样,由于lambda表单是自评估的,
    (lambda()x)
    )返回以下列表:
    (lambda()x)
    。当使用动态作用域(Emacs Lisp中的默认作用域机制)对其进行评估时,
    x
    是未绑定的-它没有值。因此产生了一个void变量错误。

    Emacs Lisp没有这样的闭包。另外,请阅读FUNCALL的文档以及如何使用它。在Emacs 24中,只要为缓冲区/文件设置了
    词法绑定,您的代码就可以工作。事实上,taht代码更为粗糙,它相当于:
    (defun foo(x)(list'lambda nil x))
    so
    (foo 66)
    返回
    (lambda()66)
    我确信这里可能会有各种各样的意外捕获…@梵蒂娜:是的,我知道反引号是什么,但你必须理解引号是什么=>它阻止了表单的计算,所以
    (defun foo(x)-(lambda()x))
    (foo 66)
    返回
    (lambda()x)
    然后您尝试执行所有这些操作,但解释器不知道它是什么。与反引号相反,反引号允许使用逗号进行计算。但是在原始文章中有一个反引号,因此它返回
    (lambda()66)
    ,而不是
    (lambda()x)
    @Vatine:是的,使用反引号它可以工作。如果文档中说lambda应该用引号格式化,那么它是针对像这样的高阶
    (mapcar'(lambda(el)(+el 1))
    ”(1 2 3 4))
    ,但是在您的情况下,您需要评估
    x`来构建闭包。