Какая разница между 'и #' в Лиспе? - PullRequest
13 голосов
/ 05 февраля 2011

Кажется, что и

(mapcar 'car '((foo bar) (foo1 bar1))) 

и

(mapcar #'car '((foo bar) (foo1 bar1)))

работают одинаково.

И я также знаю, ' означает (символ кавычки) и #' означает (имя функции функции).

Но в чем основная разница?Почему эти 2 работают в предыдущем mapcar?

Ответы [ 3 ]

14 голосов
/ 05 февраля 2011
'foo

соответствует символу FOO.

#'foo

оценивает функцию, связанную с именем FOO.

В Лиспе символ может быть вызван как функция, когда символ FOO имеет функцию привязки. Здесь CAR - это символ, имеющий функцию привязки.

Но это не работает:

(flet ((foo (a) (+ a 42)))
  (mapcar 'foo '(1 2 3 4 5)))

Это потому, что FOO как символ не имеет доступа к локальной лексической функции, и система Lisp будет жаловаться, когда foo не является функцией, определенной в другом месте.

Нам нужно написать:

(flet ((foo (a) (+ a 42)))
  (mapcar #'foo '(1 2 3 4 5)))

Здесь (функция foo) или ее сокращенное обозначение # 'foo относится к лексической локальной функции FOO.

Обратите внимание, что в

(funcall #'foo ...)

против

(funcall 'foo ...)

Последний может сделать еще одно косвенное обращение, так как ему нужно искать функцию по символу, в то время как # 'foo обозначает функцию напрямую.

Краткое описание

Если символ имеет привязку функции, вызов функции через символ работает.

9 голосов
/ 05 февраля 2011

Почему эти 2 работают в предыдущем mapcar?

Документация для mapcar гласит:

Если функция является символом, она приводится к функции, как если бы она была символ-функцией .

2 голосов
/ 03 ноября 2013

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

CL-USER> (mapcar '(lambda (x) (format t "it is ~d" x)) (list 3 5 7))
; Evaluation aborted on #<TYPE-ERROR expected-type: (OR FUNCTION SYMBOL)
             datum: (LAMBDA (X) (FORMAT T "it is ~d" X))>.

против:

CL-USER> (mapcar #'(lambda (x) (format t "it is ~d" x)) (list 3 5 7))
it is 3it is 5it is 7
(NIL NIL NIL)
...