Spec-Zone.ru › Elisp

Добавление 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API