0

In the following code the function foo calls the outer f2 function. How to make it call the anonymous function bound within the let?

(defun f2 ()
  (message "outer f2"))

(defun foo ()
  (f2))

(let ((f2 (lambda ()
            (message "inner f2"))))
  (foo)) ;; `foo' does not call `f2' in the `let', i.e. prints "outer f2"
Basil
  • 12,019
  • 43
  • 69
Talespin_Kit
  • 435
  • 2
  • 11
  • 1
    Does this answer your question? [How do I temporarily mock a function for testing?](https://emacs.stackexchange.com/questions/25055/how-do-i-temporarily-mock-a-function-for-testing) – Basil May 20 '21 at 16:35

1 Answers1

3

How to temporarily change the definition of a function?

Calling a function by its (symbol) name means calling that symbol's function slot. So, to temporarily change the definition of a function that is called by its name, you need to temporarily modify its symbol-function value. The shortest way to do that is with cl-letf; see (info "(cl) Modify Macros").

(eval-when-compile
  (require 'cl-lib))

(defun f2 ()
  (message "outer f2"))

(defun foo ()
  (f2))

(cl-letf (((symbol-function 'f2)
           (lambda () (message "inner f2"))))
  (foo)) ;; => inner f2

An alternative, more compositional approach is to use function advice, but to my knowledge there isn't a handy macro for that, and it doesn't provide any benefits in simple cases like the example above. For example:

(unwind-protect
    (progn
      (advice-add 'f2 :override
                  (lambda () (message "inner f2"))
                  '((name . my-override)))
      (foo))
  (advice-remove 'f2 'my-override)) ;; => inner f2
Basil
  • 12,019
  • 43
  • 69