Answers:
对于交互式功能(例如命令),可以使用变量this-command
或更安全的real-this-command
。不同之处在于,编写自己的函数时,可以显式更改的值this-command
。通常,这样做是为了玩一些last-command
与重复命令有关的技巧。您不应该(不能吗?)使用进行此操作real-this-command
。它始终是当前命令的名称。
我不知道非交互功能的等效项。
this-command
并且一点real-last-command
也不喜欢__func__
。例如,如果命令A调用命令B进行打印this-command
,则命令B 将打印命令A,而不是命令B,这对于功能完全无效。
我在最初的回答中说过,也许有一种方法可以在扩展/编译时而不是运行时执行,以提供更好的性能,今天我在解决这个问题的答案时终于实现了这一点:我如何确定哪个函数是在堆栈中以交互方式调用?
这是产生所有当前回溯帧的函数
(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
尽管可以在直接扩展为功能符号的宏中实现此功能,但我可能会在运行时执行功能名称查找,这对于重复调用和编译的elisp会更有效。
我在尝试为elisp编写函数调用记录程序时发现了此信息,该信息可以以不完整的形式在此处找到,但对您可能有用。https://github.com/jordonbiondo/call-log
defun
被包围时eval-and-compile
,即返回似乎无效nil
。