Tengo un código que prueba la aridad de una función. Lo uso para determinar si los argumentos opcionales agregados en las versiones recientes de un paquete están presentes. Se llama subr-arity
a las funciones incorporadas y analiza el arglist de objetos de código de bytes y lambdas.
(defun function-argspec (func)
(if (symbolp func) (setq func (indirect-function func)))
(cond
((byte-code-function-p func)
(aref func 0))
((and (consp func)
(eq (car func) 'lambda)
(consp (cdr func)))
(car (cdr func)))
))
Esto ha funcionado bien hasta Emacs 23. En Emacs 24.3 en Ubuntu 14.04, funciona bien para algunas funciones, pero no para otras.
(function-argspec 'revert-buffer)
(&optional ignore-auto noconfirm preserve-modes)
(require 'vc)
vc
(function-argspec 'vc-print-log-internal)
1283
Evidentemente, el formato del código de bytes ha cambiado de una manera que no se refleja en el manual .
(symbol-function 'vc-print-log-internal)
#[1283 \301\211\302\301\211\203\211@\303!\203\304\262A\266\202\202\210\203'\305>\202*\306>??\262\2036\307\2027\310\262\311
\312\313\314\315\316
$\317"\320\321%\312\322\323\315\316#\324"\325\326%\312\327\330\315\316!\331"\332\333%\312\334\335\315\316%\336"\325\337%&\262\207 [vc-log-short-style nil *vc-change-log* file-directory-p t directory file short long vc-log-internal-common make-byte-code 1028 \304\305\303\301\205\300\302&\207 vconcat vector [vc-call-backend print-log] 12
(fn BK BUF TYPE-ARG FILES-ARG) 771 \303\300\301\302$\207 [vc-print-log-setup-buttons] 8
(fn BK FILES-ARG RET) 257 \301\302\300#\207 [vc-call-backend show-log-entry] 5
(fn BK) 514 \305\300\301\302\303\304%\207 [vc-print-log-internal]
(fn IGNORE-AUTO NOCONFIRM)] 28
(fn BACKEND FILES WORKING-REVISION &optional IS-START-REVISION LIMIT)]
¿Cómo puedo acceder de manera confiable a la lista de argumentos de un objeto bytecode? Solo sabiendo que el arity funcionaría, no me importan los nombres de los argumentos. Más precisamente, quiero saber cuántos argumentos son obligatorios y cuántos argumentos son opcionales, o en otros términos, quiero la misma información que obtengo subr-arity
. Por supuesto, mi código debe hacer frente tanto al bytecode antiguo como al nuevo, por lo que necesito saber no solo dónde cavar sino también cuándo cavar dónde.
function-argspec
.function-argspec
función en algún lugar, incluidas las funciones de bytecode y los cierres?Respuestas:
Editar: Woo! Encontré una función que tomará la lista de argumentos normal o la versión entera y devolverá algo de una firma: ¡
byte-compile-arglist-signature
en bytecomp.el!Respuesta inicial
Espero que alguien más pueda comentar si esto está documentado o no en alguna parte, pero esto es lo que aprendí al leer
exec_byte_code
bytecode.c en la fuente de Emacs.El número que ve se usa para calcular el argspec cuando se está ejecutando el código de bytes, supongo que para el rendimiento, en realidad es bastante inteligente.
Escribí este código para mostrarle cómo calcular la aridad de una función dado ese número:
Podemos ver aquí que si corremos
arity-info
con 1283 obtenemos lo siguiente:que puede ver describe la aridad de
vc-print-log-internal
perfectamente, 5 args totales, 3 requeridos, 2 opcionales, no permite y descansa.fuente
A pedido, aquí está mi implementación de
function-argspec
yfunction-arity
. Utilicé la solución original de Jordon Biondo para Emacs 24 bytecode.fuente