Emacs Lisp:(function(lambda ...))和(lambda ...)之间的区别?

时间:2009-12-05 17:39:30

标签: emacs comparison elisp

之间有什么区别
(function (lambda ...))

(lambda ...) 

'(lambda ...)

在很多情况下,似乎有三种可以互换。

2 个答案:

答案 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