Se incluye toda la información que necesita en la C-h f add-function
que se describe el mecanismo subyacente de advice-add
.
El nuevo sistema de consejos básicamente actúa como reemplazar la definición actual de una función por la función descrita en la tabla en
C-h f add-function
, dependiendo de su elección del WHERE
argumento, solo más limpio por el simple hecho de rastrear qué comportamiento se ha definido en qué archivo fuente.
Un ejemplo con la :around
opción
El caso más general es la :around
opción, así que doy un ejemplo para eso. (Probablemente sea mejor usar WHERE
parámetros dedicados cuando sea posible, pero puede reemplazarlos por una :around
función equivalente
).
A modo de ejemplo, digamos que usted desea depurar algún uso de find-file
y desea print
la lista de parámetros cada vez que se llama. Podrías escribir
(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)
Con esta nueva implementación, todo lo que el consejo necesita se pasa como argumento. ad-get-args
se vuelve innecesario, porque los argumentos se pasan a la función de asesoramiento como argumentos de función normal (para
WHERE
argumentos para los que tiene sentido). ad-do-it
se vuelve innecesario a medida que el :around
consejo obtiene como argumentos la función y los argumentos, por lo que (ad-do-it)
se reemplaza por la forma
(apply old-function arguments)
o cuando hayas nombrado los argumentos
(funcall old-function first-arg second-arg)
que es más limpio ya que no hay formas mágicas involucradas. La modificación de los argumentos simplemente sucede al pasar valores modificados a OLD-FUNCTION
.
Otros WHERE
valores
La cadena de documentos add-function
contiene una tabla de todos los lugares de asesoramiento (o "combinadores"), y a qué son equivalentes, y explica la funcionalidad en términos de un lambda
comportamiento equivalente a la función recomendada:
`: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')
donde FUNCTION es la función de asesoramiento y OLDFUN la función donde se agrega el asesoramiento. No intente comprenderlos todos a la vez, solo seleccione un WHERE
símbolo que suene apropiado e intente comprenderlo.
O simplemente usar :around
. Por lo que puedo decir, la única ventaja de usar WHERE
s especializados :around
para todo es que obtienes un poco más de información al buscar C-h f ADVISED-FUNCTION
antes de leer la cadena de documentación del consejo. A menos que planee publicar el código que contiene el consejo, probablemente no importe.
Funciones de asesoramiento con nombre
Recomiendo usar funciones con nombre como consejo ya que proporciona muchas ventajas (algunas de ellas también se aplican al uso de funciones con nombre para ganchos):
Se muestra C-h f find-file
como
:around advice: `my-find-file-advice-print-arguments'
enlace a la definición de la función de asesoramiento, que como siempre contiene un enlace al archivo donde se definió. Si el consejo se hubiera definido como un lambda
formulario directamente en el advice-add
formulario, la cadena de documentación se mostraría en línea (¿un desastre para cadenas de documentación largas?) Y nada indicaría dónde se definió.
Puedes eliminar el consejo con
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Puede actualizar la definición del consejo sin volver a ejecutar
advice-add
o arriesgarse para mantener activa la versión anterior (ya que la ejecución
advice-add
con un cambio lambda
será reconocido como un nuevo consejo, no como una actualización de la anterior).
Comentario lateral La #'function
notación es básicamente equivalente a
'function
, excepto que ayuda al compilador de bytes a identificar símbolos como nombres de funciones y, por lo tanto, a identificar funciones que faltan (por ejemplo, debido a errores tipográficos).
M-x report-emacs-bug
. Algunos desarrolladores a veces prefieren desarrollar en lugar de documentar. ;-) Es importante que Emacs se documente a sí mismo.