Lo que quiero decir con un "contenedor transparente de funciones de 'transferencia' 'es una función, llamémosla wrapper
, que devuelve el resultado de pasar todos sus argumentos a alguna otra función, llamémosla wrappee
.
¿Cómo se hace esto en Emacs Lisp?
Nota: la wrapper
función ideal es independiente de la wrappee
firma de la función; es decir, no sabe nada del número, las posiciones, los nombres, etc. de wrappee
los argumentos de '; simplemente pasa todos sus argumentos wrappee
, como si wrappee
hubiera sido el llamado originalmente. (Sin embargo, no es necesario meterse con la pila de llamadas para reemplazar la llamada por wrapper
una llamada a wrappee
).
Publiqué una respuesta parcial a mi pregunta:
(defun wrapper (&rest args) (apply 'wrappee args))
Esto funciona solo cuando nowrappee
es interactivo. Aparentemente, la forma en que las funciones interactivas obtienen sus argumentos representa un "canal" diferente del que cubre el encantamiento. Lo que todavía necesito, por lo tanto, es una contraparte igualmente de diagnóstico de la firma para el caso en el que es una función interactiva .(&rest args)
wrappee
(&rest args)
wrappee
(Esta pregunta fue motivada por un problema descrito en esta pregunta anterior ).
En caso de que se necesite una mayor aclaración de lo que estoy pidiendo, a continuación hay un par de ejemplos que muestran los equivalentes de Python y JavaScript de lo que busco.
En Python, se muestran a continuación un par de formas estándar para implementar dicho contenedor:
def wrapper(*args, **kwargs):
return wrappee(*args, **kwargs)
# or
wrapper = lambda *args, **kwargs: wrappee(*args, **kwargs)
(Aquí *args
significa "todos los argumentos posicionales" y **kwargs
significa "todos los argumentos de palabras clave").
El equivalente de JavaScript sería algo como esto:
function wrapper () { return wrappee.apply(this, arguments); }
// or
wrapper = function () { return wrappee.apply(this, arguments); }
Para el registro, no estoy de acuerdo con que esta pregunta sea un duplicado de Cómo aplicar mapcar a una función con múltiples argumentos . No puedo explicar por qué, ya que las dos preguntas me parecen muy diferentes. Es como preguntar "explicar por qué una manzana no debe considerarse equivalente a una naranja". La mera pregunta es tan loca que uno duda que alguna vez pueda llegar a una respuesta que satisfaga a la persona que la pregunta.
advice
cosas son lo suficientemente problemáticas como para preferir evitarlas. De hecho, la motivación para esta pregunta estaba tratando de encontrar una solución a un problema que es intratable que tengo con una función aconsejó ...interactive
especificación.Respuestas:
Por supuesto, es posible incluyendo la
interactive
especificación. ¡Estamos tratando aquí con elisp ! (Lisp es el lenguaje donde las construcciones más importantes son las listas. Los formularios invocables son solo listas. Para que pueda construirlos después de su gusto).Aplicación: desea agregar alguna funcionalidad a algunas funciones de forma automática. Las funciones extendidas deben recibir nuevos nombres para que
defadvice
no sea aplicable.Primero, una versión que se ajuste exactamente a su propósito. Establecemos la celda de función (
fset
) del símbolowrapper
con toda la información requeridawrappee
y agregamos nuestras cosas adicionales.Funciona para ambas
wrappee
definiciones. La primera versión dewrappee
es interactiva y la segunda no.Pero es más conveniente definir una macro que construya las funciones extendidas. Con esto, incluso podemos especificar los nombres de las funciones después. (Bueno para una versión automatizada).
Después de ejecutar el siguiente código, puede llamar de forma
wrapper-interactive
interactiva ywrapper-non-interactive
no interactiva.Tenga en cuenta que, hasta ahora, todavía no había encontrado una manera de transferir los formularios de declaración, pero eso también debería ser posible.
fuente
edebug
. Además, hay funciones en las que lainteractive
especificación-es considerablemente más grande que el cuerpo de la función. En tales casos, la reescritura de lainteractive
especificación puede ser bastante tediosa. La pregunta y la respuesta abordan los principios requeridos.Tuve que resolver un problema muy similar
nadvice.el
, así que aquí hay una solución (que usa parte del código de nadvice.el):En comparación con las otras soluciones publicadas hasta ahora, esta tiene la ventaja de funcionar correctamente si
wrappee
se redefine con una especificación interactiva diferente (es decir, no seguirá usando la especificación anterior).Por supuesto, si desea que su envoltorio sea verdaderamente transparente, puede hacerlo de manera más simple:
fuente
advice-eval-interactive-spec
como se sugiere aquí, puedo construir la especificación interactiva que corresponde a ese contenedor dinámico.called-interactively-p
volvert
enwrappee
? Hayfuncall-interactively
pero noapply-interactively
(apply #'funcall-interactively #'wrappee args)
si quieres. Pero solo debe hacerlo si la función se llama de forma interactiva, por ejemplo(apply (if (called-interactively-p 'any) #'funcall-interactively #'funcall) #'wrappee args)
.editar: la respuesta de Tobias es mejor que esta, ya que obtiene la forma interactiva precisa y la cadena de documentos de la función envuelta.
Combinando las respuestas de Aaron Harris y kjo, podría usar algo como:
Uso:
Call wrapper con cualquiera de:
M-x
wrapper-func
fuente