Eu tenho um código que testa a aridade de uma função. Eu o uso para determinar se argumentos opcionais adicionados em versões recentes de um pacote estão presentes. Ele chama subr-arity
funções internas e analisa o arglist de objetos de bytecode e 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)))
))
Isso funcionou bem até o Emacs 23. No Emacs 24.3 no Ubuntu 14.04, ele está funcionando bem para algumas funções, mas não para outras.
(function-argspec 'revert-buffer)
(&optional ignore-auto noconfirm preserve-modes)
(require 'vc)
vc
(function-argspec 'vc-print-log-internal)
1283
Evidentemente, o formato do bytecode mudou de uma maneira que não é refletida no 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)]
Como posso acessar com segurança a lista de argumentos de um objeto de bytecode? Apenas sabendo que a aridade serviria, não me importo com os nomes dos argumentos. Mais precisamente, quero saber quantos argumentos são obrigatórios e quantos argumentos são opcionais ou, em outros termos, quero as mesmas informações que recebo subr-arity
. É claro que meu código deve lidar com os bytecodes do estilo antigo e do novo, então eu preciso saber não apenas onde cavar, mas também quando cavar onde.
function-argspec
.function-argspec
função em algum lugar, incluindo funções e fechamentos de bytecode?Respostas:
Editar: Woo! Eu encontrei uma função que pega a lista de argumentos normal ou a versão inteira e retorna um pouco de uma assinatura:
byte-compile-arglist-signature
em bytecomp.el!Resposta inicial:
Espero que alguém possa comentar se isso está ou não documentado em algum lugar, mas foi isso que aprendi lendo
exec_byte_code
dentro do bytecode.c na fonte do Emacs.O número que você vê é usado para calcular o argspec quando o código de bytes está realmente sendo executado, presumo que para desempenho, é realmente muito inteligente.
Eu escrevi este código para mostrar como calcular a aridade de uma função, dado esse número:
Podemos ver aqui que, se
arity-info
rodarmos com 1283, obtemos o seguinte:que você pode ver descreve a aridade de
vc-print-log-internal
perfeitamente, 5 args totais, 3 necessários, 2 opcionais, não permitem e descansam.fonte
Por solicitação, aqui está minha implementação de
function-argspec
efunction-arity
. Usei a solução original de Jordon Biondo para o bymacode Emacs 24.fonte