함수가 자신의 이름에 액세스 할 수 있습니까?


25

C에는 __func__현재 함수 이름을 보유하는 매직 변수 가 있습니다. Bash FUNCNAME에는 호출 스택의 모든 함수 이름을 보유 하는 배열 이 있습니다 !!!

Emacs Lisp에도 비슷한 것이 있습니까? 또는 함수가 이름에 액세스 할 수있는 간단한 방법은 무엇입니까?

Emacs Lisp 매뉴얼 (12 장 함수 또는 변수 및 함수 색인 및 ..)에서 답을 찾지 못했습니다.


2
실제로 무엇을 원하십니까?
lunaryorn

1
그것은 정확히 마술 변수가 아닙니다- 일부 컴파일러 에 의해 삽입 된 전 처리기 정의 입니다.
Sean Allred

답변:


6

대화식 기능 (예 : 명령)의 경우 변수 this-command또는보다 안전한 변수를 사용할 수 있습니다 real-this-command. 차이점은 자체 함수를 작성할 때의 값을 명시 적으로 변경할 수 있다는 것입니다 this-command. 대부분 이것은 last-command반복 명령 과 관련된 트릭을 재생하기 위해 수행됩니다 . 당신은 이것을 할 수 없습니다 real-this-command. 항상 현재 명령의 이름이됩니다.

비 대화식 기능과 동등한 기능을 알지 못합니다.


3
주의해야 this-command하며 real-last-command전혀 같지 않습니다 __func__. 예를 들어, 명령 A가 명령 B를 호출하면 명령 B가 인쇄 this-command되지 않고 명령 A가 인쇄됩니다.이 기능도 전혀 작동하지 않습니다.
Jordon Biondo

1
@JordonBiondo 합의. 함수에서는 작동하지 않습니다. phs는 우리에게 그의 맥락을 알려주지 않았으므로 이것이 그의 응용에 충분할 것이라고 생각했습니다. 당신의 대답은 더욱 강력합니다.
Tyler

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

여기서는 런타임에서 함수 이름 조회를 수행하고 있지만 반복 호출 및 컴파일 된 elisp에 더 성능이 좋은 함수 기호로 직접 확장되는 매크로에서 이것을 구현하는 것이 가능할 수도 있습니다.

불완전한 형태로 여기에서 찾을 수있는 elisp에 대한 일종의 함수 호출 로거를 작성하는 동안이 정보를 찾았지만 유용 할 수 있습니다. https://github.com/jordonbiondo/call-log


코드 주셔서 감사합니다. 이것은 내 문제를 해결하고 누군가 당신이 암시 하는 디버거의 일부인 "current-function-name"변수를 우리에게주지 않으면 며칠 안에 그것을 받아 들일 것입니다 .
phs

A는 때 그런데, 그것은 작동하지 않는 것 defun으로 둘러싸인 eval-and-compile즉, 그것은 반환 nil.
Alexander Shukaev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.