Emacs Lisp: разница между (функция (лямбда ...)) и (лямбда ...)? - PullRequest
8 голосов
/ 05 декабря 2009

В чем разница между

(function (lambda ...))

и

(lambda ...) 

и

'(lambda ...)

Кажется, что во многих случаях они взаимозаменяемы.

Ответы [ 2 ]

12 голосов
/ 06 декабря 2009

Они довольно взаимозаменяемы. Ответ в том, что function позволяет лямбда быть скомпилированным байтом, тогда как другие два не (и эквивалентны). Примечание: это не значит, что function на самом деле байтовая компиляция лямбды.

Как можно это понять? Небольшой интроспекция в Emacs дает некоторые подсказки. Для запуска: C-h f функция RET :

функция - это специальная форма в 'C исходный код ".

(функция arg)

Как и «цитата», но предпочтительнее для объекты, которые являются функциями. В байтах компиляция, «функция» вызывает его аргумент для компиляции. «Цитата» не могу этого сделать.

Хорошо, вот в чем разница между (function (lambda ...)) и '(lambda ...), первый говорит байтовому компилятору, что он может безопасно скомпилировать выражение. Принимая во внимание, что ' ed выражения могут быть не обязательно скомпилированы (поскольку они могут быть просто списком чисел.

А как насчет только (lambda ...)? C-h f лямбда RET показывает:

Лямбда - это макрос Lisp в `subr.el '.

(лямбда-аргс [строка документа] [интерактивно] тела)

Возвращает лямбда-выражение. Вызов форма (лямбда-аргумент интерактивное тело) - само цитирование; результат оценки лямбда выражение есть само выражение. Лямбда-выражение может тогда быть рассматривается как функция, то есть хранится как значение функции символа, переданное «funcall» или «mapcar» и т. д.

Следовательно, (lambda ...) и '(lambda ...) эквивалентны.

Также существует обозначение #'(lambda ...), которое является синтаксическим сахаром для (function (lambda ...)).

Для получения дополнительной информации о функциях в Emacs lisp, прочитайте Информационные страницы функций .

Просто чтобы проверить все это, вы можете ввести в буфер * 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

Итак, все три варианта использования лямбды просто создают списки, которые могут использоваться как функции (один из которых может быть скомпилирован байтами).

3 голосов
/ 26 июля 2010

Ну (quote (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

Обычно вы не хотите заключать лямбду в кавычки, если только функция, которую вы собираетесь передать лямбда, не делает с ней что-то еще, кроме funcall.

...