17

I have some code that uses flet to temporarily change the behaviour of functions.

;; prevent changing the window
(flet ((pop-to-buffer (buffer &rest args)
                      (switch-to-buffer buffer)))
   (compilation-next-error-function n reset))

However, Emacs' byte compiler gives a warning:

In ag/next-error-function:
ag.el:103:7:Warning: `flet' is an obsolete macro (as of 24.3); use either
    `cl-flet' or `cl-letf'.

However, cl-flet works differently and doesn't suit some use cases, and I believe this is one of those cases.

The options I can see are:

  1. Tell Emacs to ignore the warning somehow.

  2. Roll my own flet.

  3. Use noflet or dflet.

What is the best approach?

  • 3
    "However, cl-flet works differently". There's a second suggestion in that warning message. ;-) – Malabarba Nov 12 '14 at 19:31
  • I took the old one and just renamed it (e.g., my-flet) and removed the obsolete warning, and use that in in any package that previously required flet. – lawlist Nov 12 '14 at 19:54
12

To get the same behavior you're used to with flet, use cl-letf to change a symbols function value.

(cl-letf (((symbol-function 'pop-to-buffer)
           (lambda (buffer &rest _) (switch-to-buffer buffer))))
  (compilation-next-error-function n reset))

If you were to roll your own flet, the easy way would be macro that expands to a cl-letf form.

Edit: rolled it

(defmacro myflet (bindings &rest body)
  "Works like the old `flet'. Does not validate form structure."
  (declare (indent defun))
  `(cl-letf ,(mapcar (lambda (binding)
                       `((symbol-function ',(car binding))
                         (lambda ,(cadr binding) ,@(cddr binding))))
                     bindings)
     ,@body))

(myflet ((+ (&rest args) (apply '- args)))
  (+ 10 3 2)) ;; => 5
| improve this answer | |
  • 3
    However, keep in mind the caveat from Yann Hodique's comment to Malabarba's article: "note that Emacs 24.3.1 has a subtle bug that makes cl-letf not a proper alternative (IIRC, it does not work for flet-ing symbols that are not already fboundp). Which is why a backward-compatible version of flet is a bit... convoluted." – phils Nov 13 '14 at 21:32
12

Artur Malabarba wrote this up recently, in Understanding letf and how it replaces flet.

letf is an alias for cl-letf, and while it's most likely what you want, there's a minor caveat which Artur points out:

Unfortunately, cl-flet is not identical to the original flet—it's lexical, not dynamic.

(Nic's noflet package provides extended functionality along these lines.)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.