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

Когда должен использоваться синтаксис функции 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?
4b9b3361

Ответ 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, то, еще раз, не может быть создано предупреждение о компиляции. Таким образом, #' может помочь найти ошибки (вероятно, опечатки) раньше.

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