Se incluye toda la información que necesita en la C-h f add-functionque 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 :aroundopción
El caso más general es la :aroundopción, así que doy un ejemplo para eso. (Probablemente sea mejor usar WHEREparámetros dedicados cuando sea posible, pero puede reemplazarlos por una :aroundfunción equivalente
).
A modo de ejemplo, digamos que usted desea depurar algún uso de find-file
y desea printla 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-argsse vuelve innecesario, porque los argumentos se pasan a la función de asesoramiento como argumentos de función normal (para
WHEREargumentos para los que tiene sentido). ad-do-itse vuelve innecesario a medida que el :aroundconsejo 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 WHEREvalores
La cadena de documentos add-functioncontiene una tabla de todos los lugares de asesoramiento (o "combinadores"), y a qué son equivalentes, y explica la funcionalidad en términos de un lambdacomportamiento 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 WHEREsímbolo que suene apropiado e intente comprenderlo.
O simplemente usar :around. Por lo que puedo decir, la única ventaja de usar WHEREs especializados :aroundpara 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-filecomo
: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 lambdaformulario 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-addo arriesgarse para mantener activa la versión anterior (ya que la ejecución
advice-addcon un cambio lambdaserá reconocido como un nuevo consejo, no como una actualización de la anterior).
Comentario lateral La #'functionnotació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.