The advice feature allows modifying the behavior of a function globally. An advice definition can make calls to the original function.
(defadvice foo
(around foo-bar activate compile)
"Always set `qux' to t when running `foo'."
(let ((qux t))
ad-do-it))
The cl
package provides the flet
macro to override a function locally.
(defun foo ()
"global")
(flet ((foo ()
"local"))
(some-code-that-calls-foo))
That doesn't permit a reference to the original foo
function. What if the local override needs to call the original function?
(defun foo ()
"global")
(flet ((foo ()
(concat (foo) "+local")))
;; this will cause an infinite loop when (foo) is called
(some-code-that-calls-foo))
This straightforward approach doesn't work, for good reason: (foo)
is a recursive call to the local definition.
What's a non-cumbersome way of locally overriding a function, that allows calling the original function from the override code?
Application: monkey-patching some existing code, in a case where foo
should not be rebound globally, but the code needs to call the original. Here's the latest example I've been wanting:
(defadvice TeX-master-file
(around TeX-master-file-indirect-buffer activate compile)
"Support indirect buffers."
(flet ((buffer-file-name (&optional buffer)
(<global buffer-file-name> (buffer-base-buffer buffer))))
ad-do-it)))
I wanted to rebind buffer-file-name
locally, and call the original buffer-file-name
. Ok, in this specific case, there's a workaround, which is to use the buffer-file-name
variable. But the point of my question here is the general technique. How can I bind a function (here buffer-file-name
) locally but call the global definition from my redefinition?
This is for my .emacs
, which I keep working in Emacs 19.34, so solutions that require Emacs 24.4 are out. I do prefer solutions that cope with lexical binding cleanly though — but monkey-patching is inherently about dynamic binding.
cl-letf
is available in emacs 24.3 and before, but here is a related Q&A : emacs.stackexchange.com/a/16495/221