Вся необходимая информация включена в C-h f add-function
которые описывает основной механизм advice-add
.
Новая система рекомендаций в основном действует как замена текущего определения функции на функцию, описанную в таблице, в
C-h f add-function
зависимости от вашего выбора WHERE
аргумента, только для того, чтобы отслеживать, какое поведение было определено в каком исходном файле.
Пример с :around
опцией
Наиболее общий случай - это :around
вариант, поэтому я приведу пример для этого. (Возможно, лучше использовать выделенные WHERE
параметры, когда это возможно, но вы можете заменить все остальные эквивалентными
:around
функциями).
В качестве примера, скажем, вы хотите отладить некоторое использование find-file
и хотите print
каждый раз вызывать его список аргументов. Вы могли бы написать
(defun my-find-file-advice-print-arguments (old-function &rest arguments)
"Print the argument list every time the advised function is called."
(print arguments)
(apply old-function arguments))
(advice-add #'find-file :around #'my-find-file-advice-print-arguments)
В этой новой реализации все, что нужно совету, передается в качестве аргумента. ad-get-args
становится ненужным, потому что аргументы передаются в функцию совета как обычные аргументы функции (для
WHERE
аргументов, для которых это имеет смысл). ad-do-it
становится ненужным, так как :around
совет получает в качестве аргументов функцию и аргументы, поэтому (ad-do-it)
заменяется формой
(apply old-function arguments)
или когда вы назвали аргументы
(funcall old-function first-arg second-arg)
который чище, так как в нем нет волшебных форм. Изменение аргументов просто происходит путем передачи измененных значений в OLD-FUNCTION
.
Другие WHERE
ценности
Строка документации add-function
содержит таблицу всех советов (или «комбинаторов») и их эквивалентов, а также объясняет функциональность с точки зрения lambda
поведения, эквивалентного рекомендуемой функции:
`:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
`:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
`:around' (lambda (&rest r) (apply FUNCTION OLDFUN r))
`:override' (lambda (&rest r) (apply FUNCTION r))
`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
`:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r)))
`:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
`:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r)))
`:filter-args' (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))
(cited from `C-h f add-function')
где FUNCTION - это функция рекомендации, а OLDFUN - функция, в которую добавляется рекомендация. Не пытайтесь понять их все сразу, просто выберите WHERE
подходящий символ и попытайтесь понять его.
Или просто использовать :around
. Насколько я могу судить, единственным преимуществом использования специализированных WHERE
s над :around
всем является то, что вы получаете немного больше информации от поиска до C-h f ADVISED-FUNCTION
прочтения строки документа. Если вы не планируете публиковать код, содержащий рекомендации, это, вероятно, не имеет значения.
Названные функции совета
Я рекомендую использовать именованные функции в качестве совета, поскольку это дает много преимуществ (некоторые из них также применимы к использованию именованных функций для ловушек):
Это проявляется C-h f find-file
как
:around advice: `my-find-file-advice-print-arguments'
ссылка на определение функции совета, которая, как обычно, содержит ссылку на файл, в котором она была определена. Если бы совет был определен как lambda
форма непосредственно в advice-add
форме, строка документа была бы показана встроенной (беспорядок для длинных строк документации?), И ничто не указывало бы, где это было определено.
Вы можете удалить совет с
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Вы можете обновить определение рекомендации, не повторяя
advice-add
и не рискуя сохранять старую версию активной (поскольку работа advice-add
с измененной версией
lambda
будет распознаваться как новая рекомендация, а не как обновление старой).
Боковое замечание#'function
обозначение в основном эквивалентно
'function
, за исключением того, что он помогает байтам компилятору определить символы, имена функций и , таким образом , чтобы выявить недостающие функции (например , из - за опечатки).
M-x report-emacs-bug
. Некоторые разработчики иногда предпочитают разрабатывать, а не документировать. ;-) Важно, чтобы Emacs документировал сам.