Qual è la sostituzione corretta per flet sul nuovo emacsen?


17

Ho del codice che usa fletper cambiare temporaneamente il comportamento delle funzioni.

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

Tuttavia, il compilatore di byte di Emacs avvisa:

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

Tuttavia, cl-fletfunziona in modo diverso e non si adatta ad alcuni casi d'uso, e credo che questo sia uno di questi casi.

Le opzioni che posso vedere sono:

  1. Di 'ad Emacs di ignorare in qualche modo l'avvertimento.

  2. Rotolo mio flet.

  3. Usa noflet o dflet .

Qual è l'approccio migliore?


3
"Tuttavia, cl-flet funziona in modo diverso" . C'è un secondo suggerimento in quel messaggio di avviso. ;-)
Malabarba,

Ho preso quello vecchio e l'ho appena rinominato (ad es. my-flet) E ho rimosso l'avvertimento obsoleto, e lo uso in qualsiasi pacchetto che precedentemente richiedesse flet.
elenco delle leggi

Risposte:


13

Per ottenere lo stesso comportamento con cui sei abituato flet, usa cl-letfper cambiare il valore di una funzione di simboli.

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

Se dovessi creare il tuo flet, il modo più semplice sarebbe la macro che si espande in un cl-letfmodulo.

Modifica: arrotolato

(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

3
Tuttavia, tieni presente l'avvertenza del commento di Yann Hodique all'articolo di Malabarba: "nota che Emacs 24.3.1 ha un bug sottile che cl-letfnon costituisce un'alternativa adeguata (IIRC, non funziona per fletsimboli che non sono già fboundp). è per questo che una versione retrocompatibile di fletè un po '... contorta . "
phils,

12

Artur Malabarba lo ha scritto di recente, in Capire letf e come sostituisce flet .

letfè un alias per cl-letf, e mentre è molto probabilmente quello che vuoi, c'è un avvertimento minore che Artur sottolinea:

Sfortunatamente, cl-flet non è identico al flet originale: è lessicale, non dinamico.

(Il nofletpacchetto di Nic offre funzionalità estese in questo senso.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.