13.12.3 Способы комбинирования советов

Ниже приведены различные возможные значения для аргумента where в add-function и advice-add, указывающие, как функция совета function и исходная функция должны быть скомбинированы.

:before

Вызывает function перед старой функцией. Обе функции получают одинаковые аргументы, а возвращаемое значение композиции — это возвращаемое значение старой функции. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (apply function r) (apply oldfun r))

(add-function :before funvar function) сравнимо для однофункциональных хуков с (add-hook 'hookvar function) для обычных хуков.

:after

Вызывает function после старой функции. Обе функции получают одинаковые аргументы, а возвращаемое значение композиции — это возвращаемое значение старой функции. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (prog1 (apply oldfun r) (apply function r)))

(add-function :after funvar function) сравнимо для однофункциональных хуков с (add-hook 'hookvar function 'append) для обычных хуков.

:override

Это полностью заменяет старую функцию новой. Старую функцию, конечно, можно восстановить, если позже вызвать remove-function.

:around

Вызывает function вместо старой функции, но предоставляет старую функцию в качестве дополнительного аргумента для function. Это самая гибкая композиция. Например, это позволяет вызывать старую функцию с разными аргументами, или много раз, или внутри let-связывания, или вы можете иногда делегировать работу старой функции, а иногда полностью ее переопределить. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (apply function oldfun r))
:before-while

Вызывает function перед старой функцией и не вызывает старую функцию, если function возвращает nil. Обе функции получают одинаковые аргументы, а возвращаемое значение композиции — это возвращаемое значение старой функции. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (and (apply function r) (apply oldfun r)))

(add-function :before-while funvar function) сравнимо для однофункциональных хуков с (add-hook 'hookvar function) когда hookvar вызывается через run-hook-with-args-until-failure.

:before-until

Вызывает function перед старой функцией и вызывает старую функцию только в том случае, если function возвращает nil. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (or (apply function r) (apply oldfun r)))

(add-function :before-until funvar function) сравнимо для однофункциональных хуков с (add-hook 'hookvar function) когда hookvar вызывается через run-hook-with-args-until-success.

:after-while

Вызывает function после старой функции и только если старая функция вернула не-nil. Обе функции получают одинаковые аргументы, а возвращаемое значение композиции — это возвращаемое значение function. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (and (apply oldfun r) (apply function r)))

(add-function :after-while funvar function) сравнимо для однофункциональных хуков с (add-hook 'hookvar function 'append) когда hookvar вызывается через run-hook-with-args-until-failure.

:after-until

Вызывает function после старой функции и только если старая функция вернула nil. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (or  (apply oldfun r) (apply function r)))

(add-function :after-until funvar function) сравнимо для однофункциональных хуков с (add-hook 'hookvar function 'append) когда hookvar вызывается через run-hook-with-args-until-success.

:filter-args

Сначала вызывает function и использует результат (который должен быть списком) в качестве новых аргументов для передачи старой функции. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (apply oldfun (funcall function r)))
:filter-return

Сначала вызывает старую функцию и передает результат в function. Более конкретно, композиция двух функций ведет себя следующим образом:

(lambda (&rest r) (funcall function (apply oldfun r)))