Todas as informações necessárias estão incluídas, C-h f add-function
descrevendo o mecanismo subjacente de advice-add
.
O novo sistema de aconselhamento basicamente age como substituir a definição atual de uma função pela função descrita na tabela em
C-h f add-function
, dependendo da sua escolha do WHERE
argumento, apenas mais limpa para rastrear qual comportamento foi definido em qual arquivo de origem.
Um exemplo com a :around
opção
O caso mais geral é a :around
opção, então eu dou um exemplo para isso. (Provavelmente é melhor usar WHERE
parâmetros dedicados quando possível, mas você pode substituir todos os outros por uma :around
função equivalente
).
Apenas como exemplo, digamos que você queira depurar um pouco de uso find-file
e queira a print
sua lista de argumentos sempre que for chamada. Você poderia escrever
(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)
Com esta nova implementação, tudo o que o conselho precisa é passado como argumento. ad-get-args
torna-se desnecessário, porque os argumentos são passados para o conselho funcionam como argumentos de função normal (para
WHERE
argumentos para os quais faz sentido). ad-do-it
torna-se desnecessário à medida que o :around
conselho obtém como argumentos a função e os argumentos, (ad-do-it)
sendo substituído pelo formulário
(apply old-function arguments)
ou quando você nomeou os argumentos
(funcall old-function first-arg second-arg)
o que é mais limpo, pois não há formas mágicas envolvidas. A modificação dos argumentos simplesmente acontece passando valores modificados para OLD-FUNCTION
.
Outros WHERE
valores
A documentação de add-function
contém uma tabela de todos os locais de aconselhamento (ou "combinadores") e o que eles equivalem e explica a funcionalidade em termos de um lambda
comportamento equivalente à função 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')
onde FUNCTION é a função de aconselhamento e OLDFUN a função em que o conselho é adicionado. Não tente entender todos eles de uma só vez, basta selecionar um WHERE
símbolo que pareça adequado e tentar entendê-lo.
Ou apenas use :around
. Tanto quanto posso dizer, a única vantagem de usar WHERE
s especializados :around
para tudo é que você obtém um pouco mais de informações C-h f ADVISED-FUNCTION
antes de ler a documentação do conselho. A menos que você planeje publicar o código que contém os conselhos, provavelmente não importa.
Funções de aconselhamento nomeadas
Recomendo o uso de funções nomeadas como orientação, pois oferece muitas vantagens (algumas também se aplicam ao uso de funções nomeadas para ganchos):
Ele aparece C-h f find-file
como
:around advice: `my-find-file-advice-print-arguments'
link para a definição da função de aconselhamento, que normalmente contém um link para o arquivo em que foi definido. Se o conselho tivesse sido definido como um lambda
formulário diretamente no advice-add
formulário, a doutrina seria mostrada em linha (uma bagunça para longas doutrinas?) E nada indicaria onde foi definida.
Você pode remover o aviso com
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Você pode atualizar a definição do aviso sem executar novamente
advice-add
ou arriscar para manter a versão antiga ativa (a execução de
advice-add
uma alteração lambda
será reconhecida como novo aviso, não como uma atualização do antigo).
Observação lateral A #'function
notação é basicamente equivalente a
'function
, exceto que ajuda o compilador de bytes a identificar símbolos como nomes de funções e, assim, a identificar funções ausentes (por exemplo, devido a erros de digitação).
M-x report-emacs-bug
. Alguns desenvolvedores às vezes preferem desenvolver do que documentar. ;-) É importante que o Emacs se documente.