Зачем использовать # 'с лямбда? - PullRequest
13 голосов
/ 26 мая 2009

Почему я должен использовать # 'вместе с лямбдой? Обычно так написано, так что я думаю, что это хорошая форма. Но эти строки кажутся мне равными:

> (mapcar #'(lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)
> (mapcar (lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)

Кто-нибудь хочет рассказать новичку о разнице?

Ответы [ 2 ]

14 голосов
/ 26 мая 2009

Это отличается в разных диалектах Лисп. Следующее использует Common Lisp:

Первый # '- это краткое обозначение (функция ...) . Таким образом, следующее только текстуально отличается, но Common Lisp читает их как одинаковые:

#'(lambda (x) (* x 2))

и

(function (lambda (x) (* x 2)))

# 'является readmacro и преобразуется, когда код Lisp читается системой Lisp.

Если Лисп оценивает

(function (lambda (x) (* x 2)))

система Lisp создает функциональный объект, и FUNCTION возвращает его в качестве значения .

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

(map #'(lambda (x) (* x 2)) '(1 2 3))

(defun (y) #'(lambda (x) (* x y)))

(defparameter *twice-fn* #'(lambda (x) (* x 2)))

Теперь, что такое (лямбда (х) (* х 2))?

Это две разные вещи в зависимости от контекста.

Лямбда-выражение

Вместо имени функции можно использовать лямбда-выражение:

(function foo)   and    (function (lambda (x) (* x 2)))

и

(foo 17)    and  ((lambda (x) (* x 2)) 17)

Над двумя допустим синтаксис Common Lisp. Там можно использовать лямбда-выражение напрямую.

Обратите внимание, что следующие две формы недопустимы в Common Lisp:

(#'(lambda (x) (* x 2)) 17)   ; illegal in Common Lisp

(function #'(lambda (x) (* x 2)))  ; illegal in Common Lisp

Macro

В процессе стандартизации Common Lisp был добавлен макрос LAMBDA (он не был частью первого описания, CLtL1, Common Lisp). Это позволяет писать немного более короткий код. Пример: * * тысяча сорок восемь

(lambda (x) (* x 2))

В вышеприведенном случае LAMBDA - это макрос. Во время расширения макроса оно будет расширено до:

(function (lambda (x) (* x 2)))

Помните, что в приведенной выше форме FUNCTION внутренняя лямбда является частью лямбда-выражения, обозначает функцию и не будет расширяться.

Итак, теперь три приведенных выше примера можно записать в виде:

(map (lambda (x) (* x 2)) '(1 2 3))

(defun (y) (lambda (x) (* x y)))

(defparameter *twice-fn* (lambda (x) (* x 2)))

Он немного короче, выглядит немного менее загроможденным и выглядит немного более похожим на код Scheme. Это выглядит немного лучше для программистов, привыкших читать и писать код Scheme.

Основная информация

a) (function (lambda (x) (* x 2))) - это «истинный» способ написания кода, который возвращает функцию в качестве значения.

b) # '(лямбда (x) (* x 2)) - более короткое обозначение выше

c) (лямбда (x) (* x 2)) еще короче, но использует расширение макроса для создания формы a).

11 голосов
/ 26 мая 2009

#' является сокращением для function, которое возвращает указатель на функцию (вместо ее применения). lambda возвращает функцию, и обычно требуется указатель на эту функцию. Поскольку это так часто встречается, есть также макрос (в переменном пространстве), который делает это за вас, который также называется lambda. Обе строки кода идентичны.

Что лучше, сводится к дискуссии Lisp-1 / Lisp-2 : в Common Lisp вы можете сделать и то и другое, благодаря макросу. Как всегда, будьте последовательны.

...