Подтвердить что ты не робот

Должен ли `flet` быть заменен на` cl-flet` или `cl-letf`?

Некоторые функции elisp, которые я установил, генерируют предупреждения:

`flet' is an obsolete macro (as of 24.3); use either `cl-flet' or `cl-letf'.

Это опасно, если я просто заменил все flet на cl-flet? Если это нормально для их замены, какой из них лучше?

Если это не опасно заменить, я бы послал запросы на тягу к проектам.

Есть ли причина, по которой они не меняют?

4b9b3361

Ответ 1

flet не совпадает с cl-flet или cl-letf. Это более опасно (и, возможно, более мощное). Вот почему это устарело.

Поскольку он отличается (динамически связывает имя функции), вы должны думать в каждом случае, если необходимо заменить его на cl-flet.

Небольшой пример, когда flet не может быть заменен на cl-flet

(defun adder (a b)
  (+ a b))

(defun add-bunch (&rest lst)
  (reduce #'adder lst))

(add-bunch 1 2 3 4)
;; 10

(flet ((adder (a b) (* a b)))
  (add-bunch 1 2 3 4))
;; 24

(cl-flet ((adder (a b) (* a b)))
  (add-bunch 1 2 3 4))
;; 10

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

Ответ 2

Недавно я написал сообщение по этому вопросу. Суть сообщения в том, что лучшая замена flet (если вам нужна динамическая привязка) noflet. Это сторонняя библиотека, но это почти замена для flet (при добавлении некоторых дополнительных возможностей).

Ответ 3

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

Ответ 4

Вы можете изменить свою функцию для использования lawlist-flet или создать псевдоним - все, что я сделал, это удалить предупреждение и переименовать макрос flet в lawlist-flet:

;;;;;;;;;;;;;;;;;;;;;;;;;;;; FLET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defmacro lawlist-flet (bindings &rest body)
      "Make temporary overriding function definitions.
    This is an analogue of a dynamically scoped `let' that operates on the function
    cell of FUNCs rather than their value cell.
    If you want the Common-Lisp style of `flet', you should use `cl-flet'.
    The FORMs are evaluated with the specified function definitions in place,
    then the definitions are undone (the FUNCs go back to their previous
    definitions, or lack thereof).
    \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
      (declare (indent 1) (debug cl-flet)
    ;;           (obsolete "use either `cl-flet' or `cl-letf'."  "24.3")
                    )
      `(letf ,(mapcar
               (lambda (x)
                 (if (or (and (fboundp (car x))
                              (eq (car-safe (symbol-function (car x))) 'macro))
                         (cdr (assq (car x) macroexpand-all-environment)))
                     (error "Use `labels', not `flet', to rebind macro names"))
                 (let ((func `(cl-function
                               (lambda ,(cadr x)
                                 (cl-block ,(car x) ,@(cddr x))))))
                   (when (cl--compiling-file)
                     ;; Bug#411.  It would be nice to fix this.
                     (and (get (car x) 'byte-compile)
                          (error "Byte-compiling a redefinition of `%s' \
    will not work - use `labels' instead" (symbol-name (car x))))
                     ;; FIXME This affects the rest of the file, when it
                     ;; should be restricted to the flet body.
                     (and (boundp 'byte-compile-function-environment)
                          (push (cons (car x) (eval func))
                                byte-compile-function-environment)))
                   (list `(symbol-function ',(car x)) func)))
               bindings)
         ,@body))