Jaki jest prawidłowy zamiennik fletu na nowym emacsen?

17

Mam trochę kodu , fletktóry tymczasowo zmienia zachowanie funkcji.

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

Jednak kompilator bajtów Emacsa ostrzega:

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

Jednak cl-fletdziała inaczej i nie odpowiadał kilka przypadków użycia, i wierzę, że jest to jeden z tych przypadków.

Dostępne opcje to:

  1. Powiedz Emacsowi, aby w jakiś sposób zignorował ostrzeżenie.

  2. Rzuć moim własnym flet.

  3. Użyj noflet lub dflet .

Jakie jest najlepsze podejście?

Wilfred Hughes
źródło
3
„Jednak cl-flet działa inaczej” . W tym ostrzeżeniu jest druga sugestia. ;-)
Malabarba
Wziąłem stary i po prostu zmieniłem jego nazwę (np. my-flet) I usunąłem przestarzałe ostrzeżenie, i używam go w każdym pakiecie, który wcześniej wymagał fletu.
prawnik

Odpowiedzi:

13

Aby uzyskać takie samo zachowanie, jak zwykle flet, cl-letfzmieniaj wartość funkcji symboli.

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

Jeśli chcesz rzucić własne flet, najprostszym sposobem byłoby makro, które rozwija się do cl-letfpostaci.

Edycja: rzuciłem

(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
źródło
3
Pamiętaj jednak o zastrzeżeniu zawartym w komentarzu Yanna Hodique do artykułu Malabarby: „zauważ, że Emacs 24.3.1 ma subtelny błąd, który cl-letfnie stanowi właściwej alternatywy (IIRC, nie działa w przypadku fletsymboli, które jeszcze nie są fboundp). dlatego wersja wstecznie kompatybilna fletjest nieco ... skomplikowana . "
phils
12

Artur Malabarba napisał to niedawno w Zrozumienie letf i tego, jak zastępuje flet .

letfjest pseudonimem cl-letfi chociaż najprawdopodobniej jest to, czego chcesz, istnieje drobne zastrzeżenie, na które Artur zwraca uwagę:

Niestety cl-flet nie jest identyczny z oryginalnym - jest leksykalny, a nie dynamiczny.

( nofletPakiet Nic zapewnia rozszerzoną funkcjonalność zgodnie z tymi liniami.)

sanityinc
źródło