Cập nhật câu trả lời với tra cứu thời gian mở rộng:
Tôi đã nói trong câu trả lời ban đầu của mình rằng có thể có một cách để làm điều này vào thời gian mở rộng / biên dịch thay vì thời gian chạy để mang lại hiệu suất tốt hơn và cuối cùng tôi đã thực hiện điều đó hôm nay trong khi thực hiện câu trả lời của mình cho câu hỏi này: Làm thế nào tôi có thể xác định được chức năng nào gọi là tương tác trong ngăn xếp?
Đây là một hàm mang lại tất cả các khung backtrace hiện tại
(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)))
Sử dụng điều đó trong một macro, chúng ta có thể tra cứu ngăn xếp mở rộng để xem định nghĩa hàm nào đang được mở rộng tại thời điểm đó và đặt giá trị đó ngay trong mã.
Đây là chức năng để thực hiện việc mở rộng:
(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)))))))
Đây là hành động.
(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'"
Câu trả lời gốc:
Bạn có thể sử dụng backtrace-frame
để tra cứu ngăn xếp cho đến khi bạn thấy khung đại diện cho một lệnh gọi hàm trực tiếp và lấy tên từ đó.
(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
Ở đây tôi đang thực hiện tra cứu tên hàm trong thời gian chạy mặc dù có thể thực hiện điều này ở một macro mở rộng trực tiếp vào biểu tượng hàm sẽ hiệu quả hơn cho các cuộc gọi lặp lại và elisp được biên dịch.
Tôi đã tìm thấy thông tin này trong khi cố gắng viết một loại logger chức năng cho elisp có thể tìm thấy ở đây dưới dạng không đầy đủ, nhưng nó có thể hữu ích cho bạn. https://github.com/jordonbiondo/call-log