Jawaban yang diperbarui dengan pencarian waktu ekspansi:
Saya mengatakan dalam jawaban asli saya bahwa mungkin ada cara untuk melakukan ini pada waktu ekspansi / kompilasi alih-alih menjalankan waktu untuk memberikan kinerja yang lebih baik dan saya akhirnya mengimplementasikannya hari ini sambil mengerjakan jawaban saya untuk pertanyaan ini: Bagaimana saya bisa menentukan fungsi mana yang disebut secara interaktif di stack?
Berikut adalah fungsi yang menghasilkan semua frame backtrace saat ini
(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)))
Menggunakan itu dalam makro kita bisa mencari tumpukan ekspansi untuk melihat definisi fungsi apa yang sedang diperluas saat itu dan menempatkan nilai itu tepat di dalam kode.
Berikut adalah fungsi untuk melakukan ekspansi:
(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)))))))
Ini dia sedang beraksi.
(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'"
Jawaban asli:
Anda dapat menggunakan backtrace-frame
untuk mencari tumpukan sampai Anda melihat bingkai yang mewakili panggilan fungsi langsung dan mendapatkan nama dari itu.
(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
Di sini saya melakukan pencarian nama fungsi saat runtime meskipun mungkin untuk mengimplementasikan ini di makro yang memperluas langsung ke simbol fungsi yang akan lebih performant untuk panggilan ulang dan kompilasi elisp.
Saya menemukan informasi ini ketika mencoba untuk menulis semacam logger fungsi panggilan untuk elisp yang dapat ditemukan di sini dalam bentuk tidak lengkap, tetapi mungkin berguna bagi Anda. https://github.com/jordonbiondo/call-log