¿Cuál es el reemplazo correcto para flet en el nuevo emacsen?

17

Tengo un código que usa fletpara cambiar temporalmente el comportamiento de las funciones.

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

Sin embargo, el compilador de bytes de Emacs da una advertencia:

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

Sin embargo, cl-fletfunciona de manera diferente y no se adapta a algunos casos de uso, y creo que este es uno de esos casos.

Las opciones que puedo ver son:

  1. Dile a Emacs que ignore la advertencia de alguna manera.

  2. Rodar el mío flet.

  3. Use noflet o dflet .

¿Cuál es el mejor enfoque?

Wilfred Hughes
fuente
3
"Sin embargo, cl-flet funciona de manera diferente" . Hay una segunda sugerencia en ese mensaje de advertencia. ;-)
Malabarba
Tomé el viejo y simplemente lo renombré (por ejemplo, my-flet) y eliminé la advertencia obsoleta, y la utilicé en cualquier paquete que previamente requería flet.
abogados

Respuestas:

13

Para obtener el mismo comportamiento al que está acostumbrado flet, use cl-letfpara cambiar el valor de una función de símbolos.

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

Si flettuviera que rodar el suyo , la forma más fácil sería macro que se expande a un cl-letfformulario.

Editar: rodado

(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
fuente
3
Sin embargo, tenga en cuenta la advertencia del comentario de Yann Hodique al artículo de Malabarba: "tenga en cuenta que Emacs 24.3.1 tiene un error sutil que cl-letfno es una alternativa adecuada (IIRC, no funciona para fletforing símbolos que aún no son fboundp). es por eso que una versión compatible con versiones anteriores fletes un poco ... complicada ".
Phil
12

Artur Malabarba escribió esto recientemente, en Comprender letf y cómo reemplaza a flet .

letfes un alias cl-letfy, aunque es muy probable que sea lo que quieres, hay una advertencia menor que Artur señala:

Desafortunadamente, cl-flet no es idéntico al flet original: es léxico, no dinámico.

(El nofletpaquete de Nic proporciona una funcionalidad extendida en este sentido).

sanityinc
fuente