Search code examples
functionemacslet-binding

Temporarily overriding a function in Emacs Lisp


I would like to override a function, but only when it is called from another specific function. Following the answers to this question, I wrote the following:

(defun zzz/original () (message "Original func"))

(defun zzz/uses-original () (zzz/original))

(defun zzz/wrapper (f &rest r)
  (cl-flet
      ((zzz/original
        ()
        (message "Replacement func")))
    (apply f r)))

(advice-add #'zzz/uses-original
            :around
            #'zzz/wrapper)

I expected that calling (zzz/original) would keep printing "Original func" (it does), and that calling (zzz/uses-original) would print "Replacement func" (it doesn't: it still prints "Original func").

Note that if I inline the contents of zzz/uses-original instead of calling it through apply, then I get the expected result:

(defun zzz/wrapper (f &rest r)
  (cl-flet
      ((zzz/original
        ()
        (message "Replacement func")))
    ;; Following is a copy of the code from `zzz/uses-original':
    (zzz/original)))

So what am I doing wrong, and is there a way to get this to work?


Solution

  • As pointed out by @Rorschach, what I want can be done using cl-letf instead of cl-flet:

    (defun zzz/wrapper (f &rest r)
      (cl-letf
          ((zzz/original
            ()
            (message "Replacement func")))
        (apply f r)))