Function 有没有办法获取当前函数的函数名?

Function 有没有办法获取当前函数的函数名?,function,debugging,emacs,elisp,Function,Debugging,Emacs,Elisp,我现在这样做: (defun foo () (send-to-debug-log "Error. Function terminated." (get-current-function-name))) 硬编码函数名似乎不是一个好的做法。 任何关于实现调用我的获取当前函数名或获取函数名的建议 (defun foo () (send-to-debug-log "Error. Function terminated." 'foo))) (defun foo () (send-t

我现在这样做:

(defun foo ()
    (send-to-debug-log "Error. Function terminated." (get-current-function-name)))
硬编码函数名似乎不是一个好的做法。
任何关于实现调用我的
获取当前函数名
获取函数名的建议

(defun foo ()
    (send-to-debug-log "Error. Function terminated." 'foo)))
(defun foo ()
  (send-to-debug-log "Error. Function terminated." (nth 1 (backtrace-frame 2))))
如果你把它叫做lambda,你就得到了整个lambda。它与
apply
funcall
eval
一起工作


我认为最简单、最健壮的方法就是像现在这样显式地编写函数名。

您可以尝试以下方法:

(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))

使用包
哪个函数模式
(在melpa中),您可以通过编程方式调用该函数

(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))
更多信息:


这并不比硬编码函数名更好。您提供的函数返回
发送到调试日志
。要获取
foo
,需要将其更改为
(回溯帧3)
。换言之,此函数依赖于包含它的其他函数,因此不灵活。您可以编写一个函数,该函数返回到回溯中,直到找到正确的名称。我只是想告诉你该用什么。我在Tramp中应用了类似的技术,请参见
Tramp调试消息
。我明白了。将其放入
foo
,而应放入
send to debug log
。回溯步骤应始终保持不变。如果对代码进行字节编译,回溯的形状会有所不同,因此要使其“可靠”工作可能相当棘手。@Stefan是对的。它在未编译时返回正确的函数名。编译后,它以交互方式返回
调用
。您可以尝试使用
回溯帧
,但我认为更好的解决方案是在宏扩展期间(即编译时)将
(获取当前函数名)
替换为函数名。它不仅效率更高,而且还可以处理诸如用作回调的lambda函数之类的情况(在这种情况下,englobing函数可能根本不存在于回溯中)。因此,我强烈建议您
M-x报告emas bug
,并请求将其作为一项功能。(但是一个打字错误:
报告emacs bug
),在很难理解这一点之后。我有两个问题。是否应将
(code(apply orig fun name args))
更改为
(code(apply orig fun my current defun name args))
。为
defun添加建议对我来说也是一个新概念。它是否适用于从其他程序包和其他编译的程序包
defun
。至于第二个,它影响了
defun
的所有用法,因此它非常具有侵入性。我觉得在这一点上有些不对劲。由于
advice add
是在运行时完成的,因此
my add defun name
也必须在运行时完成,宏扩展也是如此。这种方法还增加了所有不相关的
defun
的开销。它在效率方面失去了优势?就性能而言,我认为您永远不会注意到其中的差异:它只会影响宏扩展,即编译文件的时间或加载未编译文件的时间。在那之后,
defun
基本上再也看不到了。它在complie之后就不起作用了。
哪个函数
使用当前缓冲区的
查找函数定义。
(Which-function)