Resposta atualizada com pesquisa de tempo de expansão:
Eu disse na minha resposta original que pode haver uma maneira de fazer isso no tempo de expansão / compilação, em vez do tempo de execução, para oferecer melhor desempenho e finalmente o implementei hoje, enquanto trabalhava na minha resposta para esta pergunta: Como posso determinar qual função foi chamado interativamente na pilha?
Aqui está uma função que gera todos os quadros de backtrace atuais
(defun call-stack ()
"Return the current call stack frames."
(let ((frames)
(frame)
(index 5))
(while (setq frame (backtrace-frame index))
(push frame frames)
(incf index))
(remove-if-not 'car frames)))
Usando isso em uma macro, podemos procurar a pilha de expansão para ver qual definição de função está sendo expandida no momento e colocar esse valor no código.
Aqui está a função para fazer a expansão:
(defmacro compile-time-function-name ()
"Get the name of calling function at expansion time."
(symbol-name
(cadadr
(third
(find-if (lambda (frame) (ignore-errors (equal (car (third frame)) 'defalias)))
(reverse (call-stack)))))))
Aqui está em ação.
(defun my-test-function ()
(message "This function is named '%s'" (compile-time-function-name)))
(symbol-function 'my-test-function)
;; you can see the function body contains the name, not a lookup
(lambda nil (message "This function is named '%s'" "my-test-function"))
(my-test-function)
;; results in:
"This function is named 'my-test-function'"
Resposta original:
Você pode usar backtrace-frame
para procurar a pilha até ver o quadro que representa uma chamada de função direta e obter o nome disso.
(defun get-current-func-name ()
"Get the symbol of the function this function is called from."
;; 5 is the magic number that makes us look
;; above this function
(let* ((index 5)
(frame (backtrace-frame index)))
;; from what I can tell, top level function call frames
;; start with t and the second value is the symbol of the function
(while (not (equal t (first frame)))
(setq frame (backtrace-frame (incf index))))
(second frame)))
(defun my-function ()
;; here's the call inside my-function
(when t (progn (or (and (get-current-func-name))))))
(defun my-other-function ()
;; we should expect the return value of this function
;; to be the return value of my-function which is the
;; symbol my-function
(my-function))
(my-other-function) ;; => 'my-function
Aqui, estou pesquisando o nome da função em tempo de execução, embora provavelmente seja possível implementá-la em uma macro que se expanda diretamente no símbolo da função, que teria melhor desempenho para chamadas repetidas e elisp compilado.
Encontrei essas informações ao tentar escrever um tipo de registrador de chamadas de função para elisp, que pode ser encontrado aqui em sua forma incompleta, mas pode ser útil para você. https://github.com/jordonbiondo/call-log