unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* 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).