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.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 61179 in the body.
You can then email your comments to 61179 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Mon, 30 Jan 2023 15:49:01 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Jonas Bernoulli <jonas <at> bernoul.li>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Mon, 30 Jan 2023 15:49:01 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
A function used as an around advice may advise the advised function's
interactive form, using (interactive (lambda (spec) ...)).
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)))
Or if you want to observe the failure when trying to use such an advice:
(defun -make-advice ()
(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))))
(defun -command (arg)
(interactive (list (read-string ": "))))
(advice-add '-command :around (-make-advice) '((name . "-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.
I have tried throwing an eval or two in there, but with limited success.
This gives me an inner closure, but the outside closure does not capture
the same environment it seems:
(let ((var :value))
(eval `(lambda (fn &rest args)
(interactive
,(lambda (spec)
(message "interactive: %s" var)
(advice-eval-interactive-spec spec)))
(message "body: %s" var)
(apply fn args))
t))
I got desperate and also tried things like:
(call-interactively
(let ((lex '((var . :value))))
(eval `(lambda ()
(interactive
,(eval '(lambda (spec)
(message "interactive: %s" var)
nil)
lex))
(message "body: %s" var))
lex)))
Thanks for your help!
Jonas
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Tue, 31 Jan 2023 23:34:02 GMT)
Full text and
rfc822 format available.
Message #8 received at 61179 <at> debbugs.gnu.org (full text, mbox):
> 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
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Wed, 01 Feb 2023 01:35:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 61179 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> 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))
I'm having troubles falling asleep because my brain insists on rewording
the following (even though --or perhaps exactly because-- there is not
really any need to mention it at all). So I might as well try if typing
it out helps. ;)
I actually though of that, and the initial poc worked. I did that late
at night also updated transient to use it. In the morning I noticed
that there actually were many errors, and while I suspected that the
failure had nothing to do with this part of my change, it still lost
confidence in that approach, and since I felt some pressure to get
things done before the Emacs pre-release I stopped pursuing it.
Somehow I forgot about it when I wrote the above.
Now that you have suggested the same, my confidence is back. And now
that I have written the above, I should also be able to fall asleep. ;P
> 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.
I'll only need it once; would you recommend using a helper in that case
too?
>
>
> Stefan
Good night!
Jonas
zzzzZZz
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Wed, 01 Feb 2023 22:30:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 61179 <at> debbugs.gnu.org (full text, mbox):
Stefan,
Could you please have a look at bug#61176 too? The reason I am
looking into this around advice business in the first place, is
that `post-command-hook' isn't quite working as I expected, as
described in that issue.
Thanks!
Jonas
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Wed, 01 Feb 2023 22:36:01 GMT)
Full text and
rfc822 format available.
Message #17 received at 61179 <at> debbugs.gnu.org (full text, mbox):
> I'm having troubles falling asleep because my brain insists on rewording
> the following (even though --or perhaps exactly because-- there is not
> really any need to mention it at all). So I might as well try if typing
> it out helps. ;)
>
> I actually though of that, and the initial poc worked. I did that late
> at night also updated transient to use it. In the morning I noticed
> that there actually were many errors, and while I suspected that the
> failure had nothing to do with this part of my change, it still lost
> confidence in that approach, and since I felt some pressure to get
> things done before the Emacs pre-release I stopped pursuing it.
> Somehow I forgot about it when I wrote the above.
>
> Now that you have suggested the same, my confidence is back. And now
> that I have written the above, I should also be able to fall asleep. ;P
I hope your slept well. The code I sent is, as usual, 100% guaranteed
untested, but it *should* work modulo silly errors.
> I'll only need it once; would you recommend using a helper in that case too?
Either way works.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Thu, 02 Feb 2023 14:40:01 GMT)
Full text and
rfc822 format available.
Message #20 received at 61179 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> And now that I have written the above, I should also be able to fall
>> asleep. ;P
>
> I hope your slept well.
My brain no longer saw a need to keep me awake, so yes. ;)
> The code I sent is, as usual, 100% guaranteed untested, but it
> *should* work modulo silly errors.
I haven't gotten around to play with this approach again yet.
The quote inside the function body seems a bit weird.
Jonas
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sat, 04 Feb 2023 16:27:02 GMT)
Full text and
rfc822 format available.
Message #23 received at 61179 <at> debbugs.gnu.org (full text, mbox):
> A function used as an around advice may advise the advised function's
> interactive form, using (interactive (lambda (spec) ...)).
>
> Unfortunately this inner lambda expression is not turned into a closure
> as demonstrated by this simple example:
I installed a patch in `master` which should fix this problem, both for
the case where the code is interpreted and for the case where it is
byte-compiled.
Could you confirm that it works for you?
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sat, 04 Feb 2023 23:49:01 GMT)
Full text and
rfc822 format available.
Message #26 received at submit <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:
> I installed a patch in `master` which should fix this problem, both for
> the case where the code is interpreted and for the case where it is
> byte-compiled.
Very good.
This seems to break some of my private code. Didn't look into your
change so far.
My code generates function advices with the following semantics: You
specify an alternative function and a condition (as a predicate
function). When the advice is enabled, whenever the function is called
the predicate is first checked for a non-nil result. When non-nil, the
alternative function that had been specified is called (recursive calls
are bot affected however). When nil, the original function is called.
I'm using this hack only in my init file for convenience, I like the
semantics for this purpose.
Here is a recipe for emacs -Q:
[int-lambda.el (application/emacs-lisp, inline)]
[Message part 3 (text/plain, inline)]
Worked as I wanted until now. But with your patch installed when
compiling the above snipped I get a *Compile Log* saying:
| Compiling internal form(s) at Sun Feb 5 00:36:11 2023
| int-lambda.elc: Error: ‘lambda’ defined after use in (lambda (old-spec3) (let ((test-result0 (#[0 "\300\207" [t] 1]))) (cons (if test-result0 'mel-ad-run-replacement 'mel-ad-run-original) (advice-eval-interactive-spec (if (not test-result0) old-spec3))))) (missing ‘require’ of a library file?)
| int-lambda.elc: Error: ‘lambda’ used as function name is invalid
Who is to blame?
TIA,
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sat, 04 Feb 2023 23:49:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sun, 05 Feb 2023 14:06:01 GMT)
Full text and
rfc822 format available.
Message #32 received at 61179 <at> debbugs.gnu.org (full text, mbox):
> | Compiling internal form(s) at Sun Feb 5 00:36:11 2023
> | int-lambda.elc: Error: ‘lambda’ defined after use in (lambda (old-spec3)
> | (let ((test-result0 (#[0 "\300\207" [t] 1]))) (cons (if test-result0
> | 'mel-ad-run-replacement 'mel-ad-run-original)
> | (advice-eval-interactive-spec (if (not test-result0) old-spec3)))))
> | (missing ‘require’ of a library file?)
> | int-lambda.elc: Error: ‘lambda’ used as function name is invalid
>
> Who is to blame?
You, of course.
But I think the patch below (which I just pushed to `master`) will help,
Stefan
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index e4268c2fb88..e8d639903c1 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -488,7 +488,7 @@ cconv-convert
(_ (pcase cif
('nil nil)
(`#',f
- (setf (cadr (car bf)) (if wrapped (nth 2 f) f))
+ (setf (cadr (car bf)) (if wrapped (nth 2 f) cif))
(setq cif nil))
;; The interactive form needs special treatment, so the form
;; inside the `interactive' won't be used any further.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sun, 05 Feb 2023 16:44:02 GMT)
Full text and
rfc822 format available.
Message #35 received at 61179 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> A function used as an around advice may advise the advised function's
>> interactive form, using (interactive (lambda (spec) ...)).
>>
>> Unfortunately this inner lambda expression is not turned into a closure
>> as demonstrated by this simple example:
>
> I installed a patch in `master` which should fix this problem, both for
> the case where the code is interpreted and for the case where it is
> byte-compiled.
>
> Could you confirm that it works for you?
Thanks a lot! I'll try it out tomorrow (it doesn't seem my brain feels
like work today).
Jonas
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sun, 05 Feb 2023 18:56:01 GMT)
Full text and
rfc822 format available.
Message #38 received at 61179 <at> debbugs.gnu.org (full text, mbox):
> Thanks a lot! I'll try it out tomorrow (it doesn't seem my brain feels
> like work today).
Don't worry: mine is slowly thawing now, so there's no hurry,
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#61179
; Package
emacs
.
(Sun, 05 Feb 2023 22:25:02 GMT)
Full text and
rfc822 format available.
Message #41 received at 61179 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> > Who is to blame?
> You, of course.
Oh.
> But I think the patch below (which I just pushed to `master`) will help,
> [...]
Yes, it did, thank you.
Michael.
Reply sent
to
Stefan Monnier <monnier <at> iro.umontreal.ca>
:
You have taken responsibility.
(Wed, 08 Feb 2023 14:39:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Jonas Bernoulli <jonas <at> bernoul.li>
:
bug acknowledged by developer.
(Wed, 08 Feb 2023 14:39:02 GMT)
Full text and
rfc822 format available.
Message #46 received at 61179-done <at> debbugs.gnu.org (full text, mbox):
> Could you confirm that it works for you?
[ Confirmed. ]
Thanks, closing,
Stefan
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Thu, 09 Mar 2023 12:24:09 GMT)
Full text and
rfc822 format available.
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.