* bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable
@ 2013-02-25 16:58 David Engster
2013-02-25 20:53 ` Stefan Monnier
0 siblings, 1 reply; 6+ messages in thread
From: David Engster @ 2013-02-25 16:58 UTC (permalink / raw)
To: 13813
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. :-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable
2013-02-25 16:58 bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable David Engster
@ 2013-02-25 20:53 ` Stefan Monnier
2013-02-25 21:17 ` David Engster
0 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2013-02-25 20:53 UTC (permalink / raw)
To: David Engster; +Cc: 13813
> 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
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable
2013-02-25 20:53 ` Stefan Monnier
@ 2013-02-25 21:17 ` David Engster
2013-03-11 18:15 ` Stefan Monnier
0 siblings, 1 reply; 6+ messages in thread
From: David Engster @ 2013-02-25 21:17 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 13813
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
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable
2013-02-25 21:17 ` David Engster
@ 2013-03-11 18:15 ` Stefan Monnier
2013-03-11 20:57 ` David Engster
0 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2013-03-11 18:15 UTC (permalink / raw)
To: 13813
> 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
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable
2013-03-11 18:15 ` Stefan Monnier
@ 2013-03-11 20:57 ` David Engster
2013-03-12 2:48 ` Stefan Monnier
0 siblings, 1 reply; 6+ messages in thread
From: David Engster @ 2013-03-11 20:57 UTC (permalink / raw)
To: Stefan Monnier; +Cc: 13813
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
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable
2013-03-11 20:57 ` David Engster
@ 2013-03-12 2:48 ` Stefan Monnier
0 siblings, 0 replies; 6+ messages in thread
From: Stefan Monnier @ 2013-03-12 2:48 UTC (permalink / raw)
To: 13813-done
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
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2013-03-12 2:48 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-25 16:58 bug#13813: 24.3.50; eval-and-compile in macro inhibits let-binding of variable David Engster
2013-02-25 20:53 ` Stefan Monnier
2013-02-25 21:17 ` David Engster
2013-03-11 18:15 ` Stefan Monnier
2013-03-11 20:57 ` David Engster
2013-03-12 2:48 ` Stefan Monnier
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).