이맥스 바운드 조언


14

코드에서 함수를 일시적으로 재정의하고 싶습니다.

예를 들어 다음을 보자.

(defun nadvice/load-quiet (args)
  (cl-destructuring-bind
      (file &optional noerror nomessage nosuffix must-suffix)
      args
    (list file noerror t nosuffix must-suffix)))

(defun nadvice/idle-require-quiet (old-fun &rest args)
    (advice-add 'load :filter-args #'nadvice/load-quiet)
    (apply old-fun args)
    (advice-remove #'load #'nadvice/load-quiet))

(advice-add 'idle-require-load-next :around #'nadvice/idle-require-quiet)

작동하지 않는 것 :

  • 이. 조언을 수동으로 활성화 및 비활성화하지 않고 일을 처리하는 Emacs의 단일 스레드 특성을 신뢰할 수 있다면 훨씬 더 깨끗할 것입니다.
  • cl-letforigional 함수를 참조 할 수 없으므로 :filter-args정상적으로 수행 할 수있는 작업을 수행 할 수 없습니다 .
  • cl-flet 다른 기능의 기능을 무시할 수 없습니다.
  • noflet외부 패키지이며 피하고 싶습니다. (또한 필요 이상으로 많은 일을합니다)

답변:


16

(cl-)letf원래 기능을 직접 참조하는 동안 사용할 수 없습니까?

이 같은:

;; Original function
(defun my-fun (arg)
  (message "my-fun (%s)" arg))


;; Standard call
(my-fun "arg") ;; => my-fun (arg)


;; Temporary overriding (more or less like an around advice)
(let ((orig-fun (symbol-function 'my-fun)))
  (letf (((symbol-function 'my-fun)
          (lambda (arg)
            ;; filter arguments
            (funcall orig-fun (concat "modified-" arg)))))
    (my-fun "arg")))
;; => my-fun (modified-arg)


;; The overriding was only temporary
(my-fun "arg") ;; => my-fun (arg)



재사용하려는 경우이를 매크로로 감쌀 수도 있습니다.

(defmacro with-advice (args &rest body)
  (declare (indent 1))
  (let ((fun-name (car args))
        (advice   (cadr args))
        (orig-sym (make-symbol "orig")))
    `(cl-letf* ((,orig-sym  (symbol-function ',fun-name))
                ((symbol-function ',fun-name)
                 (lambda (&rest args)
                   (apply ,advice ,orig-sym args))))
       ,@body)))

그런 다음 위의 예를 다음과 같이 다시 작성할 수 있습니다.

(defun my-fun (arg)
  (message "my-fun (%s)" arg))


(my-fun "my-arg")

(with-advice (my-fun
              (lambda (orig-fun arg)
                (funcall orig-fun (concat "modified-" arg))))
  (my-fun "my-arg"))

(my-fun "my-arg")

고마워, 이것은 내가 찾던 것입니다. 내가 바꿀 유일한 것은 cl-letf*두 가지 용도 입니다 let.
PythonNut

letf*두 바인딩에 하나의 양식 만 사용하는 매크로 버전을 추가했습니다 .
François Févotte

좋은! 많은 곳에서 조언이 필요한 경우에 사용할 수 있습니다.
PythonNut
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.