Qual é o substituto correto para o flet no novo emacsen?

17

Eu tenho algum código que usa fletpara alterar temporariamente o comportamento das funções.

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

No entanto, o compilador de bytes do Emacs emite um aviso:

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

No entanto, cl-fletfunciona de maneira diferente e não se adequa a alguns casos de uso, e acredito que esse seja um desses casos.

As opções que eu posso ver são:

  1. Diga ao Emacs para ignorar o aviso de alguma forma.

  2. Role o meu flet.

  3. Use noflet ou dflet .

Qual é a melhor abordagem?

Wilfred Hughes
fonte
3
"No entanto, o cl-flet funciona de maneira diferente" . Há uma segunda sugestão nessa mensagem de aviso. ;-)
Malabarba 12/11
Peguei o antigo e apenas o renomeei (por exemplo, my-flet) e removi o aviso obsoleto e o usei em qualquer pacote que exigisse flet anteriormente.
lawlist

Respostas:

13

Para obter o mesmo comportamento com o qual você está acostumado flet, use cl-letfpara alterar o valor da função de um símbolo.

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

Se você criar o seu próprio flet, a maneira mais fácil seria a macro que se expande para um cl-letfformulário.

Editar: rolou

(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
fonte
3
No entanto, lembre-se da ressalva do comentário de Yann Hodique ao artigo de Malabarba: "observe que o Emacs 24.3.1 possui um bug sutil que cl-letfnão é uma alternativa adequada (IIRC, ele não funciona para fletsímbolos que ainda não existem fboundp). é por isso que uma versão compatível com versões anteriores fleté um pouco ... complicada ".
phils
12

Artur Malabarba escreveu isso recentemente, em Entendendo o letf e como ele substitui o flet .

letfé um apelido para cl-letf, e embora seja mais provável o que você deseja, há uma pequena advertência que Artur aponta:

Infelizmente, o cl-flet não é idêntico ao flet original - é lexical, não dinâmico.

(O nofletpacote de Nic fornece funcionalidade estendida nesse sentido.)

sanityinc
fonte