【问题标题】:flet works, but with obsolete message; cl-flet does not workflet 有效,但消息已过时; cl-flet 不起作用
【发布时间】:2013-06-25 17:37:08
【问题描述】:

我正在尝试暂时关闭在别处定义的函数中的yes-or-no-p,然后将其恢复到原来的样子。使用 flet 有效,但会创建一个 *compile-log* 缓冲区,告诉我它已过时并改用 cl-flet。但是,cl-flet 似乎不适用于defadvice 的这种尝试——即,什么都没有发生,yes-or-no-p 仍然有效。关于如何避免错误消息并使这项工作也能发挥作用的任何想法?

(defun function-without-confirmation ()

(defadvice elmo-dop-queue-flush (around stfu activate)
      (flet ((yes-or-no-p (&rest args) t)
             (y-or-n-p (&rest args) t))
        ad-do-it))

. . . .


(ad-unadvise 'elmo-dop-queue-flush)

)

我不能把答案归功于这个答案,因为 wvxvw 已经解决了这个问题,所以我将把相关的修复放在原始问题的下面。新的宏被称为lawlist-flet instad of 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))

而且,这里是修改后的函数,它消除了与 flet 已过时有关的错误消息。

(defun function-without-confirmation ()

(defadvice elmo-dop-queue-flush (around stfu activate)
      (lawlist-flet ((yes-or-no-p (&rest args) t)
             (y-or-n-p (&rest args) t))
        ad-do-it))

. . . .


(ad-unadvise 'elmo-dop-queue-flush)

【问题讨论】:

  • 嗯,flet 是一个宏,您可以查看它的扩展内容并使用扩展版本。抱歉,我对你的代码有点困惑,好像括号不够。
  • 我正在尝试禁用yes-or-no-p,就像在这个相关线程中一样:stackoverflow.com/questions/6591043/… 如果我使用flet,代码可以工作,但是,它已被宣布为过时。但是,我确实理解您的观点,因为 Emacs 团队已宣布术语 flet 已过时而生成消息。所以你的理论应该是使用宏的胆量而不是用过时的名字来称呼它。我将找到宏并按照您的建议进行尝试,并在今天晚些时候报告。 . .
  • 效果很好——非常感谢——非常感谢!!!我已将修复添加到我最初问题的底部,因为我不值得将其发布为答案 - 归功于 wvxvw - :)
  • Stefan 的解决方案在技术上更好(如果您想坚持更长时间)。 flet 只是因为名称而过时,就像 cl 包中的其他功能一样,但它的作用应该没问题。我没有研究其他差异,但可以想象由于引入了词法绑定,cl-flet 现在可能默认使用它们,而flet 没有。

标签: emacs


【解决方案1】:

我建议你这样做:

(defvar stfu-inhibit-yonp nil)
(defadvice yes-or-no-p (around stfu activate)
  (if stfu-inhibit-yonp (setq ad-return t) ad-do-it))
(defadvice y-or-n-p (around stfu activate)
  (if stfu-inhibit-yonp (setq ad-return t) ad-do-it))

(defadvice elmo-dop-queue-flush (around stfu activate)
  (let ((stfu-inhibit-yonp t))
    ad-do-it))

与 CL 的 flet 相反,这将清楚地表明(例如在 C-h f yes-or-no-p 中)是或否 p 正在发生某些事情。

【讨论】:

  • 非常感谢 -- 我会在第二天左右试用并报告 -- 非常感谢!!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-29
  • 2016-04-17
  • 1970-01-01
  • 2010-11-14
  • 2022-12-29
  • 2022-12-02
相关资源
最近更新 更多