O que quero dizer com um "wrapper de função" transparente "de passagem" "é uma função, vamos chamá-lo wrapper
, que retorna o resultado de passar todo o seu argumento para alguma outra função, vamos chamá-lo wrappee
.
Como isso é feito no Emacs Lisp?
NB: O ideal wrapper
função é agnóstico sobre a wrappee
assinatura de função; isto é, não sabe nada sobre o número, posições, nomes, etc. dos wrappee
argumentos de; apenas passa todos os seus argumentos wrappee
, como se wrappee
tivesse sido o originalmente chamado. (Porém, não é necessário mexer na pilha de chamadas para substituí-la wrapper
por uma chamada para wrappee
.)
Publiquei uma resposta parcial à minha pergunta:
(defun wrapper (&rest args) (apply 'wrappee args))
Isso funciona apenas quando nãowrappee
é interativo. Aparentemente, a maneira como as funções interativas obtêm seus argumentos representa um "canal" diferente do que é coberto pelo encantamento. O que eu ainda preciso, portanto, é uma contrapartida igualmente magnética da assinatura para o caso em que é uma função interativa .(&rest args)
wrappee
(&rest args)
wrappee
(Esta pergunta foi motivada por um problema descrito nesta pergunta anterior .)
Caso seja necessário um esclarecimento adicional sobre o que estou pedindo, abaixo estão alguns exemplos, mostrando os equivalentes em Python e JavaScript do que estou procurando.
No Python, algumas maneiras padrão de implementar esse wrapper são mostradas abaixo:
def wrapper(*args, **kwargs):
return wrappee(*args, **kwargs)
# or
wrapper = lambda *args, **kwargs: wrappee(*args, **kwargs)
(Aqui *args
significa "todos os argumentos posicionais" e **kwargs
"todos os argumentos das palavras-chave".)
O equivalente a JavaScript seria algo como isto:
function wrapper () { return wrappee.apply(this, arguments); }
// or
wrapper = function () { return wrappee.apply(this, arguments); }
Para o registro, eu discordo que esta questão seja uma duplicata de Como aplicar o mapcar a uma função com vários argumentos . Não consigo explicar por que, uma vez que as duas perguntas parecem tão obviamente diferentes para mim. É como ser perguntado "explique por que uma maçã não deve ser considerada equivalente a uma laranja". A mera pergunta é tão louca que alguém duvida que possa encontrar uma resposta que satisfaça a pessoa que a pergunta.
advice
coisas suficientemente problemáticas para que eu prefira ficar longe disso. Na verdade, a motivação para esta questão estava tentando encontrar uma solução para um problema de outra forma intratável que tenho com uma função adviced ...interactive
especificação.Respostas:
Obviamente, é possível incluir a
interactive
especificação. Estamos lidando aqui com elisp ! (Lisp é a linguagem na qual as construções mais importantes são as listas. Os formulários que podem ser chamados são apenas listas. Assim, você pode construí-los conforme desejar.)Aplicativo: você deseja adicionar algumas funcionalidades a algumas funções automaticamente. As funções estendidas devem receber novos nomes para que isso
defadvice
não seja aplicável.Primeiro, uma versão que se encaixa exatamente no seu propósito. Definimos a célula de função (
fset
) do símbolowrapper
com todas as informações necessáriaswrappee
e adicionamos nosso material extra.Funciona para as duas
wrappee
definições. A primeira versão dowrappee
é interativa e a segunda não.Mas é mais conveniente definir uma macro que construa as funções estendidas. Com isso, podemos até especificar os nomes das funções posteriormente. (Bom para uma versão automatizada.)
Depois de executar o código abaixo, você pode ligar de forma
wrapper-interactive
interativa ewrapper-non-interactive
não interativa.Observe que, até o momento, ainda não havia uma maneira de transferir os formulários de declaração, mas isso também deveria ser possível.
fonte
edebug
. Além disso, existem funções em que ainteractive
especificação-é consideravelmente maior que o corpo da função. Nesses casos, a reescrita dainteractive
especificação pode ser bastante entediante. A pergunta e a resposta abordam os princípios exigidos.Eu tive que resolver um problema muito semelhante
nadvice.el
, então aqui está uma solução (que usa parte do código do nadvice.el):Comparado com as outras soluções postadas até agora, esta tem a vantagem de funcionar corretamente se
wrappee
for redefinida com uma especificação interativa diferente (ou seja, não continuará usando a especificação antiga).Obviamente, se você deseja que seu invólucro seja verdadeiramente transparente, você pode fazê-lo de maneira mais simples:
fonte
advice-eval-interactive-spec
como sugerido aqui, posso construir a especificação interativa que corresponde a esse invólucro dinâmico.called-interactively-p
voltart
emwrappee
? Não há,funcall-interactively
mas nãoapply-interactively
(apply #'funcall-interactively #'wrappee args)
se quiser. Mas você só deve fazer isso se a função for chamada interativamente, algo assim(apply (if (called-interactively-p 'any) #'funcall-interactively #'funcall) #'wrappee args)
.edit: A resposta de Tobias é mais agradável que essa, pois obtém a forma interativa precisa e a sequência de caracteres da função agrupada.
Combinando as respostas de Aaron Harris e kjo, você pode usar algo como:
Uso:
Wrapper de chamada com um dos seguintes:
M-x
wrapper-func
fonte