Как правильно заменить флет на новый emacsen?


17

У меня есть некоторый код, который использует fletдля временного изменения поведения функций.

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

Тем не менее, байт-компилятор Emacs выдает предупреждение:

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

Однако cl-fletработает по-другому и не подходит для некоторых случаев использования, и я считаю, что это один из таких случаев.

Варианты, которые я вижу:

  1. Скажите Emacs как-то игнорировать предупреждение.

  2. Сверните мое собственное flet.

  3. Используйте noflet или dflet .

Каков наилучший подход?


3
«Однако cl-flet работает по-другому» . В этом предупреждающем сообщении есть второе предложение. ;-)
Малабарба

Я взял старый и просто переименовал его (например, my-flet) и удалил устаревшее предупреждение, и использую его в любом пакете, который ранее требовал flet.
юрист

Ответы:


13

Чтобы получить то же поведение, с которым вы привыкли flet, используйте cl-letfдля изменения значения функции символов.

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

Если бы вы катились самостоятельно flet, то простым способом был бы макрос, который расширяется до cl-letfформы.

Редактировать: свернул

(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
Однако имейте в виду предостережение от комментария Янна Ходика к статье Малабарбы: «обратите внимание, что в Emacs 24.3.1 есть небольшая ошибка, которая делает cl-letfнеправильную альтернативу (IIRC, он не работает для fletсимволов -ing, которых еще нет fboundp). Вот почему обратно-совместимая версия fletнемного ... запутанная . "
phils

12

Артур Малабарба написал об этом недавно, в статье «Понимание letf и как она заменяет flet» .

letfэто псевдоним для cl-letf, и хотя это, скорее всего, то, что вы хотите, есть небольшая оговорка, на которую указывает Артур:

К сожалению, cl-flet не идентичен оригинальному flet - он лексический, а не динамический.

( nofletПакет Nic обеспечивает расширенную функциональность в этом направлении.)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.