之间有什么区别
(function (lambda ...))
和
(lambda ...)
和
'(lambda ...)
在很多情况下,似乎有三种可以互换。
答案 0 :(得分:12)
它们相当可互换。答案是function
启用 lambda是字节编译的,而其他两个不是(并且是等效的)。 注意:这并不意味着function
实际上是字节编译lambda。
怎么可能想出来的?一点点Emacs lisp内省提供了一些线索。首先: C-h f函数RET :
函数是'C中的一种特殊形式 源代码'。
(功能arg)
喜欢'引用',但首选 作为功能的对象。在字节中 编译,'功能'导致它 要编译的论点。 '引用' 不能这样做。
好的,这是(function (lambda ...))
和'(lambda ...)
之间的区别,第一个告诉字节编译器它可以安全地编译表达式。而' ed表达式可能不一定被编译(因为它们可能只是一个数字列表。
裸露的(lambda ...)
怎么样? C-h f lambda RET 显示:
lambda是`subr.el'中的Lisp宏。
(lambda args [docstring] [互动] 体)
返回一个lambda表达式。一个电话 形式(lambda args docstring 互动的身体)是自我引用;该 评估lambda的结果 表达式就是表达本身。 那么lambda表达式可以是 被视为一种功能,即存储为 传递了符号的函数值 'funcall'或'mapcar'等。
因此,(lambda ...)
和'(lambda ...)
是等效的。
此外,还有符号#'(lambda ...)
,它是(function (lambda ...))
的语法糖。
有关Emacs lisp中函数的更多信息,请阅读Functions info pages。
要检查所有这些,您可以在* scratch *缓冲区中键入以下内容并评估表达式:
(caddr '(lambda (x) (+ x x)))
(+ x x)
(caddr (lambda (x) (+ x x)))
(+ x x)
(caddr (function (lambda (x) (+ x x))))
(+ x x)
(equal '(lambda (x) (+ x x))
(function (lambda (x) (+ x x))))
t
(equal '(lambda (x) (+ x x))
(lambda (x) (+ x x)))
t
因此,使用lambda的所有三个变体只构建可用作函数的列表(其中一个可以是字节编译的)。
答案 1 :(得分:3)
好(quote (lambda...))
和(lambda...)
不等同(字节编译时)。引用的lambda不是字节编译的,而其他一切都是。
例如:
(defun foo (a)
(byte-code-function-p a))
(defun bar ()
(foo '(lambda () (ignore 'me))))
(defun bar2 ()
(foo (lambda () (ignore 'me))))
(defun bar3 ()
(foo (function (lambda () (ignore 'me)))))
(defun bar4 ()
(foo #'(lambda () (ignore 'me))))
(byte-compile 'bar)
(byte-compile 'bar2)
(byte-compile 'bar3)
(byte-compile 'bar4)
(bar) ; -> nil
(bar2) ; -> t
(bar3) ; -> t
(bar4) ; -> t
你通常不想引用一个lambda,除非你要传递lambda的函数正在用它做其他事情,而不仅仅是funcall
。