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 wrapperfunción ideal es independiente de la wrappeefirma de la función; es decir, no sabe nada del número, las posiciones, los nombres, etc. de wrappeelos argumentos de '; simplemente pasa todos sus argumentos wrappee, como si wrappeehubiera sido el llamado originalmente. (Sin embargo, no es necesario meterse con la pila de llamadas para reemplazar la llamada por wrapperuna 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í *argssignifica "todos los argumentos posicionales" y **kwargssignifica "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.

advicecosas 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ó ...interactiveespecificación.Respuestas:
Por supuesto, es posible incluyendo la
interactiveespecificació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
defadviceno sea aplicable.Primero, una versión que se ajuste exactamente a su propósito. Establecemos la celda de función (
fset) del símbolowrappercon toda la información requeridawrappeey agregamos nuestras cosas adicionales.Funciona para ambas
wrappeedefiniciones. La primera versión dewrappeees 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-interactiveinteractiva ywrapper-non-interactiveno 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 lainteractiveespecificación-es considerablemente más grande que el cuerpo de la función. En tales casos, la reescritura de lainteractiveespecificació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
wrappeese 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-speccomo se sugiere aquí, puedo construir la especificación interactiva que corresponde a ese contenedor dinámico.called-interactively-pvolvertenwrappee? Hayfuncall-interactivelypero 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-funcfuente