Respuesta actualizada con búsqueda de tiempo de expansión:
Dije en mi respuesta original que puede haber una manera de hacer esto en tiempo de expansión / compilación en lugar de tiempo de ejecución para dar un mejor rendimiento y finalmente lo implementé hoy mientras trabajaba en mi respuesta para esta pregunta: ¿Cómo puedo determinar qué función era llamado interactivamente en la pila?
Aquí hay una función que produce todos los marcos de traza inversa actuales
(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 eso en una macro, podemos buscar la pila de expansión para ver qué definición de función se está expandiendo en ese momento y poner ese valor en el código.
Aquí está la función para hacer la expansión:
(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)))))))
Aquí está en acción.
(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'"
Respuesta original
Puede usar backtrace-frame
para buscar la pila hasta que vea el marco que representa una llamada de función directa y obtener el nombre de eso.
(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
Aquí estoy haciendo la búsqueda del nombre de la función en tiempo de ejecución, aunque probablemente sea posible implementar esto en una macro que se expande directamente en el símbolo de la función que sería más eficiente para las llamadas repetidas y elisp compilado.
Encontré esta información al intentar escribir una especie de registrador de llamadas de función para elisp que se puede encontrar aquí en forma incompleta, pero puede ser útil para usted. https://github.com/jordonbiondo/call-log