Temporarily overriding a function in Emacs Lisp

48 views Asked by At

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?

2

There are 2 answers

0
Jmb On BEST ANSWER

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)))
0
Jmb On

Found a partial solution just after posting: using flet from the cl.el package instead of cl-flet works:

(require 'cl)

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

However this triggers a deprecation warning about cl.el, so I'm still looking for a non-deprecated solution.