GNU bug report logs -
#13813
24.3.50; eval-and-compile in macro inhibits let-binding of variable
Previous Next
Reported by: David Engster <deng <at> randomsample.de>
Date: Mon, 25 Feb 2013 17:01:02 UTC
Severity: normal
Tags: notabug
Found in version 24.3.50
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 13813 in the body.
You can then email your comments to 13813 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#13813
; Package
emacs
.
(Mon, 25 Feb 2013 17:01:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
David Engster <deng <at> randomsample.de>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Mon, 25 Feb 2013 17:01:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Recipe:
* Create a file test.el with the following contents:
(defvar myflag nil)
(defmacro mytestmacro ()
"An eval-and-compile test."
`(eval-and-compile (mytestfun)))
(defun mytestfun ()
(when myflag
(message "foo")))
(let ((myflag t))
;; Should display "foo"
(mytestmacro))
* Now call with Emacs from trunk:
emacs --batch -l test.el
* "foo" should be displayed, but isn't. The Emacs 24.2.93 pretest
however works as expected.
* Note the following:
- It works if you just 'setq' the 'myflag' variable
- If you load the file interactively and call `eval-buffer', it will
also output nothing. However, if you manually evaluate the last
expression through C-x C-e, it will work.
- The same problem occurs with `eval-when-compile', but everything
works with `progn'.
Best,
David "who will never grasp eval-and-compile"
And yes, Stefan, this bug turned up in the EIEIO test suite. :-)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#13813
; Package
emacs
.
(Mon, 25 Feb 2013 20:56:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 13813 <at> debbugs.gnu.org (full text, mbox):
> Recipe:
> * Create a file test.el with the following contents:
> (defvar myflag nil)
> (defmacro mytestmacro ()
> "An eval-and-compile test."
> `(eval-and-compile (mytestfun)))
> (defun mytestfun ()
> (when myflag
> (message "foo")))
> (let ((myflag t))
> ;; Should display "foo"
> (mytestmacro))
> * Now call with Emacs from trunk:
> emacs --batch -l test.el
> * "foo" should be displayed, but isn't. The Emacs 24.2.93 pretest
> however works as expected.
OK, you got me, I admit it, my recent change to eval-and-compile makes
it a lie. Basically, there are now 3 different times:
- compile-time
- load-time (aka "eager-macroexpansion")
- eval-time
Most eval-and-compile are used for definitions which are used in macros
(hence needed for both compile-time and load-time). For this reason,
I changed recently eval-and-compile to be (in effect)
eval-during-load-and-compile. I could turn it into
a eval-during-eval-load-and-compile, but then your above test would run
`mytestfun' twice (once with myflag=nil and then once with myflag=t)
which I don't think would please everyone either.
> * Note the following:
> - It works if you just 'setq' the 'myflag' variable
But not if you (progn (setq myflag t) (mytestmacro)). The issue is
whether the setq takes place in a separate top-level expression, in
which case it's run before eager-macroexpansion of the expression that
does the (mytestmacro).
> - The same problem occurs with `eval-when-compile', but everything
> works with `progn'.
Yes, it's basically the same problem.
> And yes, Stefan, this bug turned up in the EIEIO test suite. :-)
Could you give some details, so we can better assess the best solution?
BTW, I think eval-and-compile should only be used to wrap definitions.
Anything else is asking for trouble.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#13813
; Package
emacs
.
(Mon, 25 Feb 2013 21:20:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 13813 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier writes:
> OK, you got me, I admit it,
Ha! No one can escape the EIEIO testsuite!
> I changed recently eval-and-compile to be (in effect)
> eval-during-load-and-compile. I could turn it into a
> eval-during-eval-load-and-compile, but then your above test would run
> `mytestfun' twice (once with myflag=nil and then once with myflag=t)
> which I don't think would please everyone either.
Yep, my gut says that would create problems in EIEIO, too.
>> * Note the following:
>> - It works if you just 'setq' the 'myflag' variable
>
> But not if you (progn (setq myflag t) (mytestmacro)).
True. I didn't test that.
>> And yes, Stefan, this bug turned up in the EIEIO test suite. :-)
>
> Could you give some details, so we can better assess the best solution?
There is a flag called `eieio-error-unsupported-class-tags' which makes
`eieio-defclass' signal an error if a tag is unsupported. Since
`eieio-defclass' is the implementation of the `defclass' macro (wrapped
in `eval-and-comopile'), this flag has no effect if it is set in a
let-binding. To be specific, the test checks that this
(let ((eieio-error-unsupported-class-tags t))
(defclass class-error ()
((error-slot :initarg :error-slot
:badslottag 1))
"A class with a bad slot tag."))
is throwing an error.
> BTW, I think eval-and-compile should only be used to wrap definitions.
> Anything else is asking for trouble.
As I said: I can't wrap my head around that stuff. But the Emacs Lisp
manual specifically mentions this use case for `eval-and-compile'.
Out of curiosity I removed the `eval-and-compile' and everything seems
to work fine, which just adds to my confusion.
-David
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#13813
; Package
emacs
.
(Mon, 11 Mar 2013 18:17:01 GMT)
Full text and
rfc822 format available.
Message #14 received at 13813 <at> debbugs.gnu.org (full text, mbox):
> There is a flag called `eieio-error-unsupported-class-tags' which makes
> `eieio-defclass' signal an error if a tag is unsupported. Since
> `eieio-defclass' is the implementation of the `defclass' macro (wrapped
> in `eval-and-comopile'), this flag has no effect if it is set in a
> let-binding. To be specific, the test checks that this
> (let ((eieio-error-unsupported-class-tags t))
> (defclass class-error ()
> ((error-slot :initarg :error-slot
> :badslottag 1))
> "A class with a bad slot tag."))
> is throwing an error.
My opinion (expressed in eieio.el via: "FIXME: Most of this should be
moved to the `defclass' macro.") is that this tag-checking should be done
when expanding the `defclass' macro rather than when running
eieio-defclass. So clearly, your let-binding wouldn't affect it when
the code is byte-compiled (or when it's eagerly macroexpanded).
IOW, to be sure to get what you want, you need to be more explicit, as in:
(let ((eieio-error-unsupported-class-tags t))
(eval '(defclass class-error ()
((error-slot :initarg :error-slot
:badslottag 1))
"A class with a bad slot tag.")))
-- Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#13813
; Package
emacs
.
(Mon, 11 Mar 2013 20:59:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 13813 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier writes:
>> There is a flag called `eieio-error-unsupported-class-tags' which makes
>> `eieio-defclass' signal an error if a tag is unsupported. Since
>> `eieio-defclass' is the implementation of the `defclass' macro (wrapped
>
>> in `eval-and-comopile'), this flag has no effect if it is set in a
>> let-binding. To be specific, the test checks that this
>
>> (let ((eieio-error-unsupported-class-tags t))
>> (defclass class-error ()
>> ((error-slot :initarg :error-slot
>> :badslottag 1))
>> "A class with a bad slot tag."))
>
>> is throwing an error.
>
> My opinion (expressed in eieio.el via: "FIXME: Most of this should be
> moved to the `defclass' macro.") is that this tag-checking should be done
> when expanding the `defclass' macro rather than when running
> eieio-defclass. So clearly, your let-binding wouldn't affect it when
> the code is byte-compiled (or when it's eagerly macroexpanded).
>
> IOW, to be sure to get what you want, you need to be more explicit, as in:
>
> (let ((eieio-error-unsupported-class-tags t))
> (eval '(defclass class-error ()
> ((error-slot :initarg :error-slot
> :badslottag 1))
> "A class with a bad slot tag.")))
So in yet other words, you don't see this as a bug? If so, then please
close this report and I'll have to discuss with Eric how we deal with
this on our side.
-David
Added tag(s) notabug.
Request was from
Stefan Monnier <monnier <at> iro.umontreal.ca>
to
control <at> debbugs.gnu.org
.
(Tue, 12 Mar 2013 02:50:02 GMT)
Full text and
rfc822 format available.
Reply sent
to
Stefan Monnier <monnier <at> iro.umontreal.ca>
:
You have taken responsibility.
(Tue, 12 Mar 2013 02:50:03 GMT)
Full text and
rfc822 format available.
Notification sent
to
David Engster <deng <at> randomsample.de>
:
bug acknowledged by developer.
(Tue, 12 Mar 2013 02:50:04 GMT)
Full text and
rfc822 format available.
Message #24 received at 13813-done <at> debbugs.gnu.org (full text, mbox):
tags 13813 notabug
thanks
> So in yet other words, you don't see this as a bug? If so, then please
> close this report and I'll have to discuss with Eric how we deal with
> this on our side.
Right: the `eval-and-compile' can cause the wrapped code to be run
outside of the scope of the surrounding code, so it's normal if that
let-binding doesn't always have the effect you want.
Stefan
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Tue, 09 Apr 2013 11:24:03 GMT)
Full text and
rfc822 format available.
This bug report was last modified 12 years and 77 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.