विस्तार समय देखने के साथ अद्यतित उत्तर:
मैंने अपने मूल उत्तर में कहा कि बेहतर प्रदर्शन देने के लिए रन टाइम के बजाय विस्तार / संकलन समय पर ऐसा करने का एक तरीका हो सकता है और मैंने आखिरकार इस प्रश्न के लिए अपने जवाब पर काम करते हुए आज इसे लागू किया: मैं यह कैसे निर्धारित कर सकता हूं कि कौन सा कार्य था स्टैक में अंतःक्रियात्मक रूप से कहा जाता है?
यहां एक फ़ंक्शन है जो सभी वर्तमान बैकट्रेस फ़्रेमों की पैदावार करता है
(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)))
उस मैक्रो का उपयोग करके हम विस्तार स्टैक को देख सकते हैं कि फ़ंक्शन परिभाषा को किस समय विस्तारित किया जा रहा है और उस मान को कोड में सही रखा गया है।
यहाँ विस्तार करने के लिए समारोह है:
(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)))))))
यहाँ यह कार्रवाई में है।
(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'"
मूल उत्तर:
आप backtrace-frame
तब तक स्टैक देखने के लिए उपयोग कर सकते हैं जब तक कि आप एक सीधा फ़ंक्शन कॉल का प्रतिनिधित्व करने वाले फ़्रेम को न देखें और उस से नाम प्राप्त करें।
(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
यहाँ मैं रनटाइम पर फंक्शन नाम लुकअप कर रहा हूँ, हालांकि इसे सीधे मैक्रो पर लागू करना संभव है जो सीधे फंक्शन सिंबल में फैलता है जो रिपीट कॉल और संकलित एलीस्प के लिए अधिक प्रदर्शनकारी होगा।
मुझे यह जानकारी मिल गई जबकि एक प्रकार का फंक्शन कॉल लकड़हारा लिखने की कोशिश की जा रही थी, जो यहाँ अपूर्ण रूप में पाया जा सकता है, लेकिन यह आपके लिए उपयोगी हो सकता है। https://github.com/jordonbiondo/call-log