Aktualisierte Antwort mit Suche nach Erweiterungszeit:
Ich sagte in meiner ursprünglichen Antwort, dass es eine Möglichkeit geben könnte, dies zur Expansions- / Kompilierungszeit anstatt zur Laufzeit zu tun, um eine bessere Leistung zu erzielen, und implementierte dies schließlich heute, während ich an meiner Antwort für diese Frage arbeitete: Wie kann ich bestimmen, welche Funktion war? interaktiv im Stack aufgerufen?
Hier ist eine Funktion, die alle aktuellen Backtrace-Frames liefert
(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)))
Wenn wir das in einem Makro verwenden, können wir im Erweiterungsstapel nachsehen, welche Funktionsdefinition gerade erweitert wird, und diesen Wert direkt in den Code einfügen.
Hier ist die Funktion, um die Erweiterung durchzuführen:
(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)))))))
Hier ist es in Aktion.
(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'"
Ursprüngliche Antwort:
Mit können Sie backtrace-frame
den Stapel nachschlagen, bis Sie einen Frame sehen, der einen direkten Funktionsaufruf darstellt, und den Namen daraus erhalten.
(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
Hier mache ich die Suche nach Funktionsnamen zur Laufzeit, obwohl es wahrscheinlich möglich ist, dies in einem Makro zu implementieren, das direkt in das Funktionssymbol erweitert wird, das für wiederholte Aufrufe und kompiliertes Elisp leistungsfähiger wäre.
Ich habe diese Information gefunden, als ich versucht habe, eine Art Funktionsaufruf-Logger für elisp zu schreiben, der hier in unvollständiger Form zu finden ist, aber er könnte für Sie nützlich sein. https://github.com/jordonbiondo/call-log