Добавление advice к именованным функциям
Часто advice используется для именованных функций и макросов. Можно просто использовать add-function, например:
(add-function :around (symbol-function 'fun) #'his-tracing-function)
Но вместо этого следует использовать advice-add и advice-remove. Этот отдельный набор функций для управления фрагментами advice, применёнными к именованным функциям, предоставляет следующие дополнительные возможности по сравнению с add-function: он умеет работать с макросами и автозагружаемыми функциями, позволяет describe-function сохранять исходную строку документации и одновременно документировать добавленный advice, а также позволяет добавлять и удалять фрагменты advice ещё до определения функции.
advice-add может быть полезен для изменения поведения существующих вызовов существующей функции без необходимости переопределять функцию целиком. Однако это может стать источником ошибок: существующие вызывающие код функции могут рассчитывать на её прежнее поведение и работать неправильно после его изменения с помощью advice. Advice также может затруднить отладку, если отлаживающий не заметит или забудет, что функция была изменена с помощью advice.
Обратите внимание, что проблемы связаны не с advice как таковым, а с изменением именованной функции. Изменять именованную функцию с помощью низкоуровневых примитивов, таких как fset, defalias или cl-letf, ещё проблематичнее. С этой точки зрения advice — лучший способ изменить именованную функцию, поскольку он отслеживает изменения, поэтому их можно перечислить и отменить.
К изменению именованной функции следует прибегать только в тех случаях, когда изменить поведение Emacs каким-либо другим способом невозможно. Если того же результата можно добиться с помощью хука, предпочтительнее использовать его (см. Хуки). Если вы просто хотите изменить действие определённой клавиши, возможно, лучше написать новую команду и переназначить ей привязки клавиш старой команды (см. Переназначение команд).
Если вы пишете код для выпуска, предназначенный для использования другими, постарайтесь не включать в него advice. Если для функции, к которой вы хотите добавить advice, нет подходящего хука, обратитесь к разработчикам Emacs и предложите добавить такой хук. В частности, исходные файлы самого Emacs не должны добавлять advice к функциям Emacs. (В настоящее время из этого правила есть несколько исключений, но мы намерены их исправить.) Как правило, чище создать новый хук в foo и сделать так, чтобы bar использовал этот хук, чем добавлять advice в foo из bar.
Специальные формы (см. Специальные формы) не могут иметь advice, однако advice можно добавлять к макросам почти так же, как к функциям. Конечно, это не повлияет на код, для которого макрорасширение уже выполнено, поэтому необходимо установить advice до раскрытия макроса.
Добавлять advice к примитиву (см. Что такое функция?) можно, но обычно этого не следует делать по двум причинам. Во-первых, некоторые примитивы используются механизмом advice, и добавление к ним advice может привести к бесконечной рекурсии. Во-вторых, многие примитивы вызываются непосредственно из C, и такие вызовы игнорируют advice; в результате возникает запутанная ситуация, когда одни вызовы (из кода Lisp) учитывают advice, а другие (из кода C) — нет.
- Макрос: define-advice symbol (where lambda-list &optional name depth) &rest body
Этот макрос определяет фрагмент advice и добавляет его к функции с именем symbol. Если name не равно
nil, advice получает имяsymbol@nameи устанавливается под именем name; в противном случае advice является анонимным. Объяснение остальных аргументов см. вadvice-add.
- Функция: advice-add symbol where function &optional props
Добавляет advice function к именованной функции symbol. Аргументы where и props имеют то же значение, что и для
add-function(см. Примитивы для управления advice).
- Команда: advice-remove symbol function
Удаляет advice function из именованной функции symbol. Вместо function также можно указать
nameфрагмента advice. При интерактивном вызове запрашивает именованную функцию function, к которой добавлен advice, и удаляемый advice.
- Функция: advice-member-p function symbol
Возвращает значение, отличное от
nil, если advice function уже добавлен к именованной функции symbol. Вместо function также можно указатьnameфрагмента advice.
- Функция: advice-mapc function symbol
Вызывает function для каждого фрагмента advice, добавленного к именованной функции symbol. Функция function вызывается с двумя аргументами: функцией advice и её свойствами.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Named-Functions.html