GNU bug report logs -
#61179
lambda inside interactive form of around advice isn't a closure
Previous Next
Reported by: Jonas Bernoulli <jonas <at> bernoul.li>
Date: Mon, 30 Jan 2023 15:49:01 UTC
Severity: normal
Done: Stefan Monnier <monnier <at> iro.umontreal.ca>
Bug is archived. No further changes may be made.
Full log
View this message in rfc822 format
> Unfortunately this inner lambda expression is not turned into a closure
> as demonstrated by this simple example:
>
> ;; -*- lexical-binding: t -*-
> (let ((var :value))
> (lambda (fn &rest args)
> (interactive
> (lambda (spec)
> (message "interactive: %s" var)
> (advice-eval-interactive-spec spec)))
> (message "body: %s" var)
> (apply fn args)))
Hmm... in Emacs-29, we fixed a part of this problem.
E.g.
(call-interactively
(let ((x 42))
(lambda (f)
(interactive (list (lambda () x)))
(+ (funcall f) 1))))
should return 43 (even when byte-compiled).
But indeed, the fix currently fails to account for such
"interactive advice" :-(
> Could this be changed in the next Emacs release? Even if this should
> make it into 29.1 (which I doubt), it would still be very useful for me
> if this could somehow be rewritten to also work in older Emacs releases.
The above fix is non-trivial, I'm afraid (e.g. it relies on OClosures
internally). For your above code, I think I'd try something like:
(let* ((var :value)
(interactive-advice
(lambda (spec)
(message "interactive: %s" var)
(advice-eval-interactive-spec spec)))
(advice-body
(lambda (fn &rest args)
(message "body: %s" var)
(apply fn args))))
(eval `(lambda (&rest args)
(interactive ,interactive-advice)
(apply ',advice-body args))
t))
where the last 4 lines are "generic" and could be turned into
a helper function if you end up using it several times.
This should also minimize the amount of code that's hidden from the
compiler by the backquote.
Stefan
This bug report was last modified 2 years and 159 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.