O recurso de aconselhamento permite modificar o comportamento de uma função globalmente. Uma definição de conselho pode fazer chamadas para a função original.
(defadvice foo
(around foo-bar activate compile)
"Always set `qux' to t when running `foo'."
(let ((qux t))
ad-do-it))
O cl
pacote fornece a flet
macro para substituir uma função localmente.
(defun foo ()
"global")
(flet ((foo ()
"local"))
(some-code-that-calls-foo))
Isso não permite uma referência à foo
função original . E se a substituição local precisar chamar a função original?
(defun foo ()
"global")
(flet ((foo ()
(concat (foo) "+local")))
;; this will cause an infinite loop when (foo) is called
(some-code-that-calls-foo))
Essa abordagem direta não funciona, por um bom motivo: (foo)
é uma chamada recursiva à definição local.
Qual é a maneira não complicada de substituir localmente uma função, que permite chamar a função original a partir do código de substituição?
Aplicação: aplicar um patch em algum código existente, em um caso em foo
que não deve ser recuperado globalmente, mas o código precisa chamar o original. Aqui está o exemplo mais recente que eu queria:
(defadvice TeX-master-file
(around TeX-master-file-indirect-buffer activate compile)
"Support indirect buffers."
(flet ((buffer-file-name (&optional buffer)
(<global buffer-file-name> (buffer-base-buffer buffer))))
ad-do-it)))
Eu queria voltar a ligar buffer-file-name
localmente e ligar para o original buffer-file-name
. Ok, neste caso específico, há uma solução alternativa, que é usar a buffer-file-name
variável. Mas o ponto da minha pergunta aqui é a técnica geral. Como posso vincular uma função (aqui buffer-file-name
) localmente, mas chamar a definição global da minha redefinição?
Isso é para o meu .emacs
, que continuo trabalhando no Emacs 19.34, para que soluções que exijam o Emacs 24.4 estejam disponíveis. No entanto, prefiro soluções que lidem com a ligação lexical de maneira limpa - mas a correção de macacos é inerentemente relacionada à ligação dinâmica.
fonte
cl-letf
está disponível em emacs 24.3 e antes, mas aqui é um relacionados Q & A: emacs.stackexchange.com/a/16495/221Respostas:
Armazene a função original (obtida com
symbol-function
) em uma variável local e usefuncall
para chamar o objeto de função armazenado nessa variável. Pesado, mas funciona principalmente.Isso funciona principalmente , na medida em que faz o que deveria fazer, mas pode quebrar em raras circunstâncias. Como o Emacs Lisp não tem uma maneira primitiva de definir os slots de função dos símbolos localmente (apenas os slots variáveis, com
let
),flet
define as ligações e as restauraunwind-protect
. Se o código morrer porque o aninhamento de chamada excedeumax-lisp-eval-depth
ou se a ligação for modificada durante a execução desta função (por exemplo, porque você está depurando o aviso), é possível que o slot de função do símbolo não seja restaurado. Você pode tomar precauções contra a perda acidental de algumas funções.Outro método é armazenar uma cópia da função. Isso tem a vantagem de que a função original nunca é perdida.
Isso seria bom nesse caso específico, porque
buffer-file-name
é uma função interna que provavelmente não será recuperada, mas não rastreará redefinições da função global (por exemplo, para adicionar conselhos a essa função).fonte
nadvice
receita para o mesmo?