2016-03-10 2 views
3
(defun foo() 
    (send-to-debug-log "Error. Function terminated." (get-current-function-name))) 

Я в настоящее время сделать это:Есть ли способ получить имя функции текущей функции?

(defun foo() 
    (send-to-debug-log "Error. Function terminated." 'foo))) 

Hard кодирования имя функции, кажется, не является хорошей практикой. Любые предложения по внедрению get-current-function-name или get-function-name-that-call-me.

+1

Вы можете попробовать играть в режиме backtrace-frame, но я думаю, что лучшим решением было бы заменить '(get-current-function-name) на имя функции во время макрорасширения (т. во время компиляции). Он не только был бы более эффективным, но также обрабатывал бы такие случаи, как лямбда-функции, используемые в качестве обратных вызовов (где функция englobing может вообще отсутствовать в backtrace). Поэтому я настоятельно рекомендую вам «M-x report-emas-bug» и запросить это как функцию. – Stefan

+0

Что сказал @Stefan. (Но опечатка: 'report-emacs-bug'.) – Drew

ответ

3
(defun foo() 
    (send-to-debug-log "Error. Function terminated." (nth 1 (backtrace-frame 2)))) 
+0

Это не лучше, чем жесткий код имя функции. Предоставленная функция возвращает 'send-to-debug-log'. Чтобы получить 'foo', он должен измениться как' (backtrace-frame 3) '. Другими словами, эта функция зависит от других функций, входящих в нее, и не является гибкой. – tom

+0

Вы можете написать функцию, которая возвращается в обратном направлении, пока не найдет собственное имя. Я просто хотел показать вам, что использовать. Я применяю подобный метод в Tramp, см. 'Tramp-debug-message'. –

+0

Я понимаю. Вместо этого, помещая его в 'foo', его следует поместить в' send-to-debug-log'. Шаги обратного хода всегда должны быть постоянными. – tom

1

Вот то, что, кажется, работает очень хорошо:

(defun calling-function() 
    (let ((n 6) ;; nestings in this function + 1 to get out of it 
     func 
     bt) 
    (while (and (setq bt (backtrace-frame n)) 
       (not func)) 
     (setq n (1+ n) 
       func (and bt 
         (nth 0 bt) 
         (nth 1 bt)))) 
    func)) 

Если вы вызываете его в лямбда, вы получаете весь лямбда. Он работает с apply, funcall и eval.

Я думаю, что самый простой, надежный способ - просто написать имя функции, как вы сейчас делаете.

+1

Форма обратной линии отличается, если вы байт-компилируете код, поэтому заставить его работать «надежно» может быть довольно сложным. – Stefan

+0

@ Стейфан прав. Он возвращает правильное имя функции, если оно не было скомпилировано. После компиляции он возвратил 'call-interactiveively'. – tom

1

Вы могли бы попробовать что-то вроде:

(defconst my-defun-macros '(defun cl-defun defmacro cl-defmacro)) 

(defun my-add-defun-name (orig-fun name &rest args) 
    (let* ((my-current-defun-name (if (consp name) (cadr name) name)) 
     (macroexpand-all-environment 
      (cons (cons 'my-get-current-function-name 
         (lambda() my-current-defun-name)) 
       macroexpand-all-environment)) 
     (code (apply orig-fun name args))) 
    (macroexpand-all code macroexpand-all-environment))) 

(defmacro my-get-current-function-name() 
    "Return current defun's name. 
Only works within the advised macros in `my-defun-macros'." 
    (error "my-get-current-function-name used outside of a defun")) 

(dolist (m my-defun-macros) 
    (advice-add m :around #'my-add-defun-name)) 
+0

После непростого понимания этого. У меня есть два вопроса. Если '(code (apply orig-fun name args))' будет изменен на '(code (apply orig-fun my-current-defun-name args))'. – tom

+0

Добавление совета к 'defun' также является новой концепцией для меня. Будет ли он применяться к 'defun' из других пакетов и других скомпилированных пакетов? – tom

+0

Что касается вашего первого вопроса, нет, 'имя' должно быть передано немодифицированным в исходный макрос. Что касается второго, это влияет на все использование 'defun', так что это очень навязчиво. – Stefan

1

С пакетом (в melpa), можно программно вызвать функцию

(Which-function) 
более

информация:

+0

Это не сработало после комплимента. Функция 'which-function' использует' with-current-buffer', чтобы найти функцию defintion. – tom

Смежные вопросы