क्या फ़ंक्शंस उनके नाम तक पहुंच सकते हैं?


25

सी में जादू चर __func__है जो वर्तमान फ़ंक्शन नाम रखता है। बैश FUNCNAMEमें, कॉलिंग स्टैक में सभी फ़ंक्शन के नाम रखने वाला एक सरणी है !!!

क्या Emacs Lisp में एक समान बात है? या किसी फ़ंक्शन के लिए किसी भी सरल तरीके से उसके नाम तक पहुंच हो सकती है?

मुझे एमएसीएस लिस्प मैनुअल (वेरिएबल्स और फ़ंक्शंस के सूचकांक या अध्याय और ..) पर कोई उत्तर नहीं मिला है।


2
वास्तव में आपको इसके लिए क्या चाहिए?
चंद्र

1
यह वास्तव में एक जादुई चर नहीं है - यह कुछ संकलक द्वारा डाला गया एक पूर्व-प्रोसेसर परिभाषा है ।
सीन एलेड

जवाबों:


6

इंटरैक्टिव फ़ंक्शंस के लिए, अर्थात, आप चर this-commandया सुरक्षित का उपयोग कर सकते हैं real-this-command। अंतर यह है कि जब आप अपने स्वयं के कार्यों को लिखते हैं, तो आप स्पष्ट रूप से मूल्य बदल सकते हैं this-command। अधिकतर यह last-commandआदेशों को दोहराने से संबंधित चालें खेलने के लिए किया जाता है । आपको ऐसा नहीं करना चाहिए real-this-command। यह हमेशा वर्तमान कमांड का नाम होगा।

मुझे गैर-संवादात्मक कार्यों के लिए एक समकक्ष के बारे में पता नहीं है।


3
यह नोट करना महत्वपूर्ण है this-commandऔर ऐसा real-last-commandबिल्कुल नहीं है __func__। उदाहरण के लिए यदि कमांड A कॉल कमांड B को प्रिंट this-commandकरता है जो कमांड A को प्रिंट करेगा, B नहीं, यह भी फ़ंक्शन के लिए बिल्कुल भी काम नहीं करता है।
जोर्डन बियोनडो

1
@ जोर्डनबियोनो सहमत। मैंने ध्यान दिया कि यह फ़ंक्शन के लिए काम नहीं करता है। phs ने हमें अपना संदर्भ नहीं दिया, इसलिए मैंने अनुमान लगाया कि यह उनके आवेदन के लिए पर्याप्त हो सकता है। आपका जवाब अधिक मजबूत है, कोई सवाल नहीं।
टायलर

22

विस्तार समय देखने के साथ अद्यतित उत्तर:

मैंने अपने मूल उत्तर में कहा कि बेहतर प्रदर्शन देने के लिए रन टाइम के बजाय विस्तार / संकलन समय पर ऐसा करने का एक तरीका हो सकता है और मैंने आखिरकार इस प्रश्न के लिए अपने जवाब पर काम करते हुए आज इसे लागू किया: मैं यह कैसे निर्धारित कर सकता हूं कि कौन सा कार्य था स्टैक में अंतःक्रियात्मक रूप से कहा जाता है?

यहां एक फ़ंक्शन है जो सभी वर्तमान बैकट्रेस फ़्रेमों की पैदावार करता है

(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


कोड के लिए धन्यवाद। यह मेरी समस्या को हल करता है और मैं इसे कुछ दिनों में स्वीकार करूंगा जब तक कि कोई हमें "वर्तमान-फ़ंक्शन-नाम" चर नहीं देता है जो आपके द्वारा संकेत किए गए डीबगर का हिस्सा है
phs

वैसे, जब defunयह संलग्न होता है, तो यह काम नहीं करता है eval-and-compile, अर्थात यह वापस आ जाता है nil
अलेक्जेंडर शुकेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.