【问题标题】:Should `flet` be replaced with `cl-flet` or `cl-letf` ?`flet` 应该替换为 `cl-flet` 或 `cl-letf` 吗?
【发布时间】:2013-09-19 13:11:59
【问题描述】:

我安装的一些 elisp 函数会产生警告:

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

如果我简单地将所有flet 替换为cl-flet 会不会很危险? 如果可以更换,哪个更好?

如果替换它不危险,我会向项目发送拉取请求。

他们不改变它有什么原因吗?

【问题讨论】:

    标签: emacs


    【解决方案1】:

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

    【讨论】:

    • 我明白了。所以,这并不容易,因为我可以简单地替换所有功能。谢谢!
    • 如果你想降低你的烦恼程度,只需从源中删除flet的定义,剥离obsolete并将其放入你的.emacs中。删除 flet 而不是你的应该是包编写者的工作。
    • 另一个选项是(setq byte-compile-warnings '(not obsolete))
    • 字节编译警告在我看来非常有用,所以我不会禁用它们。他们擅长捕捉可变错别字或格式错误的 let 绑定。但据我所知,关于 flet 警告没有重写包 api,我无能为力。
    • 有没有办法在不使用 flet 的情况下获得旧行为?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      cl-letf 函数可用于动态绑定函数,正如 Artur 在 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))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-29
          • 1970-01-01
          • 1970-01-01
          • 2016-04-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多