Genişletme süresi aramasıyla güncellenmiş yanıt:
Orijinal cevabımda, daha iyi performans vermek için çalışma zamanı yerine genişleme / derleme zamanında bunu yapmanın bir yolu olabileceğini söyledim ve nihayet bu soruyu yanıtlamada çalışırken bugün uyguladım: Hangi fonksiyonun ne olduğunu nasıl belirleyebilirim etkileşimli yığında çağırdı?
İşte tüm mevcut backtrace çerçevelerini veren bir fonksiyon
(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)))
Bunu bir makroda kullanarak, o sırada hangi işlev tanımının genişletildiğini görmek için genişletme yığınını arayabilir ve bu değeri doğrudan koda koyabiliriz.
Genişletme yapma işlevi:
(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)))))))
İşte eylemde.
(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'"
Orijinal cevap:
backtrace-frame
Doğrudan bir işlev çağrısını temsil eden kareyi görene kadar yığını aramak için kullanabilirsiniz ve bu adın adını alın.
(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
Burada, çalışma zamanı işlev adı araması yapıyorum, ancak bunu doğrudan çağrılar ve derlenmiş elisp için daha performans gösteren doğrudan işlev sembolüne genişleten bir makroda uygulamak mümkün olabilir.
Bu bilgiyi elisp için eksik formda bulunan bir tür işlev çağrısı günlüğü yazmaya çalışırken buldum, ancak sizin için yararlı olabilir. https://github.com/jordonbiondo/call-log