Katsumi Yamaoka yamaoka@jpl.org submitted Emacs bug#22317:
25.0.50; mh-e: wrong usage of cl-flet
Hi,
mh-e uses Gnus functions to render MIME messages and uses the mh-cl-flet macro to modify some of them. Currently mh-e always loads cl (see mh-acros.el), so both cl-flet and flet are available and mh-cl-flet will become cl-flet:
,----
| ;; Emacs 24 renamed flet to cl-flet.
| (defalias 'mh-cl-flet
| (if (fboundp 'cl-flet)
| 'cl-flet
| 'flet))
`----
However, cl-flet is quite unlike flet, IIUC. For instance, if cl-flet is used, the mh-cl-flet code in mh-display-emphasis
,----
| ;; (defun mh-display-emphasis ()
| ;; "Display graphical emphasis."
| ;; (when (and mh-graphical-emphasis-flag (mh-small-show-buffer-p))
| (mh-cl-flet
| ((article-goto-body ())) ; shadow this function to do nothing
| (save-excursion
| (goto-char (point-min))
| (article-emphasize)))
| ;; ))
`----
will be expanded to
,----
| (progn
| (save-excursion
| (goto-char (point-min))
| (article-emphasize)))
`----
whereas if flet is used, it will be expanded to:
,----
| (let* ((vnew (cl-function (lambda nil
| (cl-block article-goto-body))))
| (old (symbol-function 'article-goto-body)))
| (unwind-protect
| (progn
| (fset 'article-goto-body vnew)
| (save-excursion
| (goto-char (point-min))
| (article-emphasize)))
| (fset 'article-goto-body old)))
`----
Note that the former doesn't achieve the original target, i.e.,article-goto-body is not modified while running article-emphasize.
I don't know how it damages the behavior of mh-e, but I think it should be fixed anyway. If mh-e keeps loading cl as ever,mh-cl-flet can be:
(defalias 'mh-cl-flet 'flet)
Otherwise use this complete Emacs-Lisp style flet emulation macro (a copy of gmm-flet that exists in only the Gnus git master):
(defmacro mh-cl-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.
\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
(require 'cl)
(if (fboundp 'cl-letf)
`(cl-letf ,(mapcar (lambda (binding)
`((symbol-function ',(car binding))
(lambda ,@(cdr binding))))
bindings)
,@body)
`(flet ,bindings ,@body)))
(put 'mh-cl-flet 'lisp-indent-function 1)
(put 'mh-cl-flet 'edebug-form-spec
'((&rest (sexp sexp &rest form)) &rest form))
I'm not the right person to install it since I'm not a mh-e user,sorry.
Regards,
Katsumi had previously posted this in 2012-12-06:
Hi,
IMHO, isn't what you really want cl-letf, not cl-flet? Though it needs to have some accessories so as to work like flet.
Where the `gmm-flet' macro, that uses cl-letf, is now available only in Ma Gnus. Why it is not in the Emacs trunk is that I've removed it following RMS's statement:
http://thread.gmane.org/gmane.emacs.diffs/118608/focus=155306
As for Gnus such a macro is not necessary for the present if it is used with the Emacs version that bundles it, however I have no idea for MH-E better than overriding. :-<
Here is Katsumi's reply to my response on 2013-04-05:
Hi,
Bill Wohler wrote:
What I wanted to say was that some mh-e functions that use mh-cl-flet for utilizing Gnus functions won't work as expected. For example,AFAIU, the function mh-display-with-external-viewer tries to substitute mm-handle-set-external-undisplayer with mh-handle-set-external-undisplayer while performing mm-display-external. Its mh-cl-flet form is expanded as folows:
However, as you can see, mh-handle-set-external-undisplayer will never be used. This is the case where mh-cl-flet is an alias to cl-flet, that happens under Emacs 24.3 and up. If it is an alias to flet, the expanded form will be:
This is what it should be, isn't it? For that purpose, cl-flet is a mischoice, cl-letf should be used instead. Here is a macro that uses cl-letf to emulate flet:
With replacing mh-cl-flet with this, the form shown above will be expanded like the following:
Note that, gmm-flet exists only in the Gnus Git master, not the Emacs trunk. Maybe some Emacs core developers don't like it. Related readings: https://lists.gnu.org/archive/html/emacs-devel/2012-12/msg00096.html and the thread.
Anyway, the macro name mh-cl-flet had better be renamed into something like mh-flet, I think.
It looks like this was fixed by
though checkdoc complains that the "bindings" argument is never mentioned in the docstring for mh-flet.
I'm going to have to agree with Mike. We'll put the flet bug to rest unless we hear otherwise. Resolving as fixed.