Tutte le informazioni necessarie sono incluse in C-h f add-function
cui viene descritto il meccanismo sottostante di advice-add
.
Il nuovo sistema di consulenza agisce sostanzialmente come la sostituzione della definizione corrente di una funzione con la funzione descritta nella tabella in
C-h f add-function
, a seconda della scelta WHERE
dell'argomento, solo più pulita per tenere traccia di quale comportamento è stato definito in quale file sorgente.
Un esempio con l' :around
opzione
Il caso più generale è l' :around
opzione, quindi do un esempio per questo. (Probabilmente è meglio usare WHERE
parametri dedicati quando possibile, ma è possibile sostituirsi a vicenda con una :around
funzione equivalente
).
Ad esempio, supponiamo che tu voglia eseguire il debug di un certo uso find-file
e desideri il print
suo elenco di argomenti ogni volta che viene chiamato. Potresti scrivere
(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 questa nuova implementazione, tutto ciò di cui ha bisogno il consiglio viene passato come argomento. ad-get-args
diventa inutile, perché gli argomenti vengono passati alla funzione di avviso come normali argomenti di funzione (per
WHERE
argomenti per i quali ha senso). ad-do-it
diventa inutile quando il :around
consiglio ottiene come argomenti la funzione e gli argomenti, quindi (ad-do-it)
viene sostituito dal modulo
(apply old-function arguments)
o quando hai nominato gli argomenti
(funcall old-function first-arg second-arg)
che è più pulito in quanto non vi sono forme magiche coinvolte. La modifica degli argomenti avviene semplicemente passando a valori modificati OLD-FUNCTION
.
Altri WHERE
valori
La documentazione di add-function
contiene una tabella di tutti i posti di consulenza (o "combinatori"), a cosa sono equivalenti e spiega la funzionalità in termini di lambda
comportamento equivalente alla funzione consigliata:
`: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')
dove FUNCTION è la funzione di avviso e OLDFUN la funzione in cui viene aggiunto l'avviso. Non cercare di capirli tutti in una volta, basta selezionare un WHERE
simbolo che sembra appropriato e provare a capirlo.
O semplicemente usa :around
. Per quanto ne so, l'unico vantaggio dell'uso di WHERE
s specializzati in :around
tutto è che puoi ottenere un po 'più di informazioni guardando C-h f ADVISED-FUNCTION
prima di leggere la documentazione del consiglio. A meno che tu non preveda di pubblicare il codice contenente i consigli, probabilmente non importa.
Funzioni di consulenza nominate
Consiglio di usare le funzioni nominate come consiglio poiché offre molti vantaggi (alcune si applicano anche all'uso delle funzioni nominate per gli hook):
Si presenta in C-h f find-file
as
:around advice: `my-find-file-advice-print-arguments'
collegamento alla definizione della funzione di avviso, che come al solito contiene un collegamento al file in cui è stato definito. Se il consiglio fosse stato definito come un lambda
modulo direttamente nel advice-add
modulo, il docstring verrebbe mostrato in linea (un pasticcio per lunghi docstring?) E nulla indicherebbe dove è stato definito.
Puoi rimuovere il consiglio con
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Puoi aggiornare la definizione del consiglio senza rieseguire
advice-add
o rischiare di mantenere attiva la vecchia versione (poiché l'esecuzione
advice-add
con una modifica lambda
verrà riconosciuta come nuova consulenza, non come aggiornamento a quella precedente).
Nota laterale La #'function
notazione è sostanzialmente equivalente a
'function
, tranne per il fatto che aiuta il compilatore di byte a identificare i simboli come nomi di funzione e quindi a identificare le funzioni mancanti (ad esempio a causa di errori di battitura).
M-x report-emacs-bug
. Alcuni sviluppatori a volte preferiscono sviluppare piuttosto che documentare. ;-) È importante che Emacs si documenti.