应该用`cl-flet`或`cl-letf`替换'flet`吗?

时间:2013-09-19 13:12:00

标签: emacs

我安装的某些elisp函数会生成警告:

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

如果我只是用flet替换所有cl-flet,会有危险吗? 如果可以更换它们,哪一个更好?

如果更换它没有危险,我会向项目发送拉动请求。

是否有某些原因他们不改变它?

4 个答案:

答案 0 :(得分:9)

fletcl-fletcl-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暂时生成一个阶乘。

答案 1 :(得分:6)

我最近在这个主题上写了post。帖子的要点是flet的最佳替代品(如果需要动态绑定)是noflet。它是第三方库,但它几乎是flet的替代品(同时增加了一些额外的功能)。

答案 2 :(得分:3)

cl-letf函数可用于动态绑定函数,正如Artur在this博客条目中所述。

答案 3 :(得分:1)

您可以修改您的功能以使用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))