[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#61179: lambda inside interactive form of around advice isn't a closu
From: |
Stefan Monnier |
Subject: |
bug#61179: lambda inside interactive form of around advice isn't a closure |
Date: |
Tue, 31 Jan 2023 18:33:18 -0500 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
> 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