Когда должен использоваться синтаксис функции Emacs #?
В принципе, когда следует использовать процедуру Emacs Lisp function
? Я не нашел примеров, в которых есть разница в поведении, если вы передаете функции в качестве аргументов 'like-this
или #'like-this
. На самом деле, если я оцениваю (eq 'goto-char #'goto-char)
, он возвращает t
.
Код Emacs Lisp, с которым я столкнулся, редко использует function
/#'
; авторы просто quote
/'
все.
Пример: (add-hook 'emacs-lisp-hook 'turn-on-eldoc-mode)
Однако я могу найти несколько контрпримеров. Здесь один из исходного кода Emacs 24.3 electric.el
:
(add-hook 'post-self-insert-hook
#'electric-indent-post-self-insert-function
'append)
Угадай и дальнейшие вопросы:
- Это просто стилистическая конвенция Lisp -2?
- Это связано с байтовой компиляцией?
- Это имеет значение только для библиотек? Например, если вы хотите, чтобы ваш код запускался в огромном количестве сред и версий Emacs? (Следствие было бы, если бы вы просто "топик-мастеринг", тогда вам не нужно беспокоиться обо всем этом.)
- Когда следует цитировать лямбда-выражения? Когда я могу оставить их без кавычек?
Например, (do-something '(lambda …
по сравнению с (do-something (lambda …
- Было ли какое-то ограничение в более ранней версии Emacs, которая породила эти грани elisp? Например, могу ли я в основном игнорировать разницу между
'
и #'
, если я использую версию Emacs более позднюю, чем X?
Ответы
Ответ 1
function
(aka #'
) используется для цитирования функций, тогда как quote
(aka '
) используется для цитирования данных. Теперь в Emacs- Lisp символ, чья функциональная ячейка является функцией, сам по себе является функцией, поэтому #'symbol
практически совпадает с 'symbol
на практике (это намерение отличается, первое из которых ясно показывает, что не говоря только о символе "символ", а о функции с именем "символ" ).
Место, где различие не просто стилистично, - это при цитировании lambdas: '(lambda ...)
- выражение, которое вычисляет список, первым элементом которого является символ lambda
. Вам разрешено применять к нему такие вещи, как car
и cdr
, но вы не должны называть его так, как если бы это была функция (хотя на практике это работает нормально). Напротив, #'(lambda ...)
(который может быть записан просто (lambda ...)
), является выражением, которое оценивает функцию. Это означает, что вы не можете применить к нему car
, но байтовый компилятор может заглянуть внутрь #'(lambda ...)
, выполнить макроразложение в нем, предупредить вас, если то, что он находит, не выглядит кошерным и т.д.; Для лексического связывания даже нужно заглянуть внутрь, чтобы найти свободные переменные, к которым относится эта функция.
Ответ 2
В elisp #'
(по сути) чисто байт-компиляция (edit: и с Emacs 24, также лексические закрытия); но вам также, вероятно, никогда не понадобится его использовать.
#'...
является кратким для (function ...)
, который является просто вариантом '...
/(quote ...)
, который также указывает на байтовый компилятор, что он может скомпилировать цитированную форму как функцию.
Однако в современных Emacs (IIRC это было не всегда так), (lambda ...)
эквивалентен #'(lambda ...)
, поэтому я считаю, что вам редко (если когда-либо) нужно писать #'
.
Вы также редко хотели бы использовать '(lambda ...)
по причинам, которые развивал Стефан (но 'symbol
в порядке).
Это описано в руководстве под C-h i g (elisp) Anonymous Functions
RET (хотя в последнем фрагменте кода примера имеется ошибка, так как она идентична предыдущему примеру ( в Emacs 24.3.1)).
(n.b. Ответ Стефана является окончательным, но я сохраню его здесь, поскольку он, надеюсь, дополняет его.)
Ответ 3
В дополнение к различиям при цитировании форм (lambda ...)
в последнее время (по состоянию на Emacs 24.4) было изменено на bytecomp.el такое, что предупреждение генерируется при использовании формы #'symbol
, но функция не является как известно, определяется в конце компиляции.
Написание всех функциональных символов синтаксисом функции #'symbol
, а не синтаксисом 'symbol
, таким образом, несколько предпочтительнее, поскольку он позволяет байтовому компилятору проверять, были ли вы использованы имена функций, которые фактически определены.
Ранее (Emacs 24.3 и более ранние версии), в то время как байт-компилятор предупреждал, когда вы вызываете функцию как (no-such-function ...)
, и она не определена или не импортирована из другого файла, что-то вроде (mapcar #'no-such-function ...)
создало бы только среду выполнения -error без предупреждения о компиляции.
Изменение означает, что оба этих сценария теперь выдают предупреждения во время компиляции; однако, если вы используете (mapcar 'no-such-function ...)
без использования функции-quoting, то, еще раз, не может быть создано предупреждение о компиляции. Таким образом, #'
может помочь найти ошибки (вероятно, опечатки) раньше.
Функция-цитирование также помогает в стиле программирования сверху вниз, поскольку байт-компилятор затем перечисляет функции, которые вы еще не реализовали (но пропустите функции, указанные с обычной цитатой).