Quel est le remplacement correct pour flet sur un nouvel emacsen?

17

J'ai du code qui permet fletde changer temporairement le comportement des fonctions.

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

Cependant, le compilateur d'octets d'Emacs donne un avertissement:

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'.

Cependant, cl-fletfonctionne différemment et ne convient pas à certains cas d'utilisation, et je pense que c'est l'un de ces cas.

Les options que je peux voir sont:

  1. Dites à Emacs d'ignorer l'avertissement d'une manière ou d'une autre.

  2. Roulez moi-même flet.

  3. Utilisez noflet ou dflet .

Quelle est la meilleure approche?

Wilfred Hughes
la source
3
"Cependant, cl-flet fonctionne différemment" . Il y a une deuxième suggestion dans ce message d'avertissement. ;-)
Malabarba
J'ai pris l'ancien et l'ai simplement renommé (par exemple, my-flet) et supprimé l'avertissement obsolète, et l'utiliser dans n'importe quel paquet qui nécessitait auparavant flet.
lawlist

Réponses:

13

Pour obtenir le même comportement que celui auquel vous êtes habitué flet, utilisez cl-letfpour modifier la valeur d'une fonction de symboles.

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

Si vous deviez rouler le vôtre flet, la méthode la plus simple serait la macro qui se développe en un cl-letfformulaire.

Edit: roulé

(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
Jordon Biondo
la source
3
Cependant, gardez à l'esprit la mise en garde du commentaire de Yann Hodique à l'article de Malabarba: "notez que Emacs 24.3.1 a un bug subtil qui cl-letfne constitue pas une alternative appropriée (IIRC, il ne fonctionne pas pour les fletsymboles -ing qui ne le sont pas déjà fboundp). c'est pourquoi une version rétrocompatible de fletest un peu ... compliquée . "
phils
12

Artur Malabarba l'a écrit récemment, dans Comprendre letf et comment il remplace flet .

letfest un alias pour cl-letf, et bien que ce soit probablement ce que vous voulez, il y a une petite mise en garde qu'Artur souligne:

Malheureusement, cl-flet n'est pas identique au flet d'origine - il est lexical, pas dynamique.

(Le nofletpackage de Nic fournit des fonctionnalités étendues dans ce sens.)

sanityinc
la source