Подтвердить что ты не робот

Какая разница между 'и #' в Lisp?

Кажется, что

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

и

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

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

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

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

4b9b3361

Ответ 1

'foo

оценивает символ FOO.

#'foo

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

В Lisp символ может быть вызван как функция, когда символ 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 обозначает функцию напрямую.

Резюме

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

Ответ 2

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

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

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

Ответ 3

Попробуйте передать анонимную функцию (лямбда) на ваш 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)