all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* eval-when-compile
@ 2012-07-27  5:01 Achim Gratz
  2012-07-27  6:26 ` eval-when-compile Pascal J. Bourguignon
  2012-08-08 21:13 ` eval-when-compile Johan Bockgård
  0 siblings, 2 replies; 10+ messages in thread
From: Achim Gratz @ 2012-07-27  5:01 UTC (permalink / raw)
  To: emacs-devel


[I hope this is the correct list for asking this question.]

I've been trying to use eval-when-compile to switch between alternate
versions of code based on a compile-time decision.  However it seems
that either I don't understand the documentation or something doesn't
quite work.

Compiling this source file:

--8<---------------cut here---------------start------------->8---
(eval-when-compile
  (if t
      (defvar unquoted-t "true")
    (defvar unquoted-nil "false")))
(eval-when-compile
  (if nil
      '(defvar quoted-t "true")
    '(defvar quoted-nil "false")))
--8<---------------cut here---------------end--------------->8---

results in an empty (except the header of course) byte-compiled file.  I
expected the quoted version to compile

`(defvar quoted-nil "false")´

which is what that form evaluates to.  When I wrap a defmacro around it
and call that macro outside the eval-when-compile:

--8<---------------cut here---------------start------------->8---
(eval-when-compile
  (defmacro ewc-macro (&rest body)
    (if nil
	'(defvar macro-t "true")
      '(defvar macro-nil "false"))))
(ewc-macro)
--8<---------------cut here---------------end--------------->8---

then I get the expected output in the byte-compiled file, but it seems
there must be an easier way to do that.  The eval-when-compile in this
version suppresses the macro definition itself being byte-compiled of
course.


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

SD adaptation for Waldorf rackAttack V1.04R1:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27  5:01 eval-when-compile Achim Gratz
@ 2012-07-27  6:26 ` Pascal J. Bourguignon
  2012-07-27  7:41   ` eval-when-compile PJ Weisberg
  2012-07-27 17:50   ` eval-when-compile Achim Gratz
  2012-08-08 21:13 ` eval-when-compile Johan Bockgård
  1 sibling, 2 replies; 10+ messages in thread
From: Pascal J. Bourguignon @ 2012-07-27  6:26 UTC (permalink / raw)
  To: emacs-devel

Achim Gratz <Stromeko@nexgo.de> writes:

> [I hope this is the correct list for asking this question.]
>
> I've been trying to use eval-when-compile to switch between alternate
> versions of code based on a compile-time decision.  However it seems
> that either I don't understand the documentation or something doesn't
> quite work.
>
> Compiling this source file:
>
> (eval-when-compile
>   (if t
>       (defvar unquoted-t "true")
>     (defvar unquoted-nil "false")))
> (eval-when-compile
>   (if nil
>       '(defvar quoted-t "true")
>     '(defvar quoted-nil "false")))

C-h f eval-when-compile RET

    Like `progn', but evaluates the body at compile time if you're compiling.
    Thus, the result of the body appears to the compiler as a quoted constant.
    In interpreted code, this is entirely equivalent to `progn'.

What more can I add?


The above source will evaluate, when you compile the file:

    (defvar unquoted-t "true")
    '(defvar quoted-nil "false")

When you load the file, it won't evaluate anything.

So what you've done is to define inside the compiler a variable named
unquoted-t, and nothing else.  Once the compiler exits, there remains
nothing of that variable.


> results in an empty (except the header of course) byte-compiled file.  I
> expected the quoted version to compile
> `(defvar quoted-nil "false")´

Why?  You never evaluated it, even at compilation time, much less at
load time!



> which is what that form evaluates to.  When I wrap a defmacro around it
> and call that macro outside the eval-when-compile:
>
> (eval-when-compile
>   (defmacro ewc-macro (&rest body)
>     (if nil
> 	'(defvar macro-t "true")
>       '(defvar macro-nil "false"))))
> (ewc-macro)

Here, you're defining a macro at compilation time.  When compiling this
file, the macro is known and (ewc-macro) expands to (defvar macro-nil
"false") so that's compiled into the elc file, and that's the only thing
that's loaded.

If you try to load the .el file directly, then the macro is not defined,
and you're trying to call a function named (ewc-macro) which will fail.


> then I get the expected output in the byte-compiled file, but it seems
> there must be an easier way to do that.  The eval-when-compile in this
> version suppresses the macro definition itself being byte-compiled of
> course.

It's bad to restrict yourself to compilation-time.  One can also load
the sources directly (it's considered "run-time").

If you put this:

    (require 'cl)
    (eval-when (compile) (print '(hi compile)))
    (eval-when (load)    (print '(hi load)))
    (eval-when (eval)    (print '(hi run)))

in a file named /tmp/time.el and then evaluate the following forms, the
messages appear in *Messages*:


    (byte-compile-file "/tmp/time.el")

    (hi compile)
    t


    (load "/tmp/time.elc")

    (hi load)
    t


    (load "/tmp/time.el")

    (hi run)
    t

So, while it's conceivable to have a big program loaded into the
compiler that you don't want to load at run-time (eg. you're writing a
compiler for a different language, load it, and then compile a program
in this language thru a macro, and you want just the resulting lisp code
of this compilation to be included in the .elc), but in general, you
want to have access to the macros also at run-time (for interactive
use).

Now indeed, if you have decisions to make at compilation time, you need
to define variables and functions at compilation time to compute those
decisions.

    (eval-when-compile ; or (require 'cl) (eval-when (compile) …
      (defun decide-what-to-generate ()
         …))

    (defmacro generate-alternative ()
      (if (decide-what-to-generate) ; called at compilation time.
         `(progn
             (defvar *first-option* 42)
             (defun use-first-option ()
               (do-something-with *first-option*)))
         `(progn
             (defvar *second-option* 'zz)
             (defun use-second-option ()
               (do-something-with *second-option*)))))

    (generate-alternative)


Now of course, the problem is that when you load this file,  you don't
know what you will get.  Will you get a function named use-first-option
or a function named use-second-option?  Doubt.  Depends on what happened
when you compiled that file…  So I think it's not a good idea to do that
kind of things.

    
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27  6:26 ` eval-when-compile Pascal J. Bourguignon
@ 2012-07-27  7:41   ` PJ Weisberg
  2012-07-27  8:11     ` eval-when-compile Pascal J. Bourguignon
  2012-07-27 17:50   ` eval-when-compile Achim Gratz
  1 sibling, 1 reply; 10+ messages in thread
From: PJ Weisberg @ 2012-07-27  7:41 UTC (permalink / raw)
  To: Pascal J. Bourguignon; +Cc: emacs-devel

On Thu, Jul 26, 2012 at 11:26 PM, Pascal J. Bourguignon
<pjb@informatimago.com> wrote:
> Achim Gratz <Stromeko@nexgo.de> writes:

>> (eval-when-compile
>>   (if t
>>       (defvar unquoted-t "true")
>>     (defvar unquoted-nil "false")))

Try evaluating that block.  It has side effects, of course, but the result is:

'unquoted-t

That's just a symbol, sitting there all alone and not doing anything.
There are no instructions to execute, so the byte compiler doesn't
have anything to output.

>> (eval-when-compile
>>   (if nil
>>       '(defvar quoted-t "true")
>>     '(defvar quoted-nil "false")))

That evaluates to:

'(defvar quoted-nil "false")

That's a list.  Just a list, not a function call.  Once again, nothing
for the byte compiler to do.

eval-when-compile isn't a macro; it results in a value, not code.

>> (eval-when-compile
>>   (defmacro ewc-macro (&rest body)
>>     (if nil
>>       '(defvar macro-t "true")
>>       '(defvar macro-nil "false"))))
>> (ewc-macro)

*That's* a macro.  eval-when-compile still outputs a value, but the
macro call outputs code.  Here, the .elc file will be the equivalent
of:

'ewc-macro
(defvar macro-nil "false")

Line 1 is a no-op, but line 2 is just what you want.

> Here, you're defining a macro at compilation time.  When compiling this
> file, the macro is known and (ewc-macro) expands to (defvar macro-nil
> "false") so that's compiled into the elc file, and that's the only thing
> that's loaded.
>
> If you try to load the .el file directly, then the macro is not defined,
> and you're trying to call a function named (ewc-macro) which will fail.

That's incorrect.  Things inside the eval-when-compile get evaluated
when the .el file is loaded, but not when the .elc file is loaded.
It's *not* the equivalent of Common Lisp's (eval-when (compile)
body...)

-PJ

Gehm's Corollary to Clark's Law: Any technology distinguishable from
magic is insufficiently advanced.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27  7:41   ` eval-when-compile PJ Weisberg
@ 2012-07-27  8:11     ` Pascal J. Bourguignon
  0 siblings, 0 replies; 10+ messages in thread
From: Pascal J. Bourguignon @ 2012-07-27  8:11 UTC (permalink / raw)
  To: emacs-devel

PJ Weisberg <pj@irregularexpressions.net> writes:

> On Thu, Jul 26, 2012 at 11:26 PM, Pascal J. Bourguignon
> <pjb@informatimago.com> wrote:
>> If you try to load the .el file directly, then the macro is not defined,
>> and you're trying to call a function named (ewc-macro) which will fail.
>
> That's incorrect.  Things inside the eval-when-compile get evaluated
> when the .el file is loaded, but not when the .elc file is loaded.
> It's *not* the equivalent of Common Lisp's (eval-when (compile)
> body...)

You're right, I misread C-h f eval-when-compile.  
Hence the importance of reading well the documentation!


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27  6:26 ` eval-when-compile Pascal J. Bourguignon
  2012-07-27  7:41   ` eval-when-compile PJ Weisberg
@ 2012-07-27 17:50   ` Achim Gratz
  2012-07-28  0:52     ` eval-when-compile Stephen J. Turnbull
  2012-07-28 18:04     ` eval-when-compile PJ Weisberg
  1 sibling, 2 replies; 10+ messages in thread
From: Achim Gratz @ 2012-07-27 17:50 UTC (permalink / raw)
  To: emacs-devel

Pascal J. Bourguignon writes:
> C-h f eval-when-compile RET
>
>     Like `progn', but evaluates the body at compile time if you're compiling.
>     Thus, the result of the body appears to the compiler as a quoted constant.
>     In interpreted code, this is entirely equivalent to `progn'.
>
> What more can I add?

I read that.  It doesn't seem to work that way or has some strings
attached that aren't obvious to me from the documentation.

> The above source will evaluate, when you compile the file:
>
>     (defvar unquoted-t "true")
>     '(defvar quoted-nil "false")

No.  They will evaluate to

unquoted-t
(defvar quoted-nil "false")

The unquoted variant was only there to check if maybe there's another
`(quote …)´ snuck in.  I expected the defvar form to compile, but it
doesn't.

> When you load the file, it won't evaluate anything.

Actually they will evaluate to the very same thing, per the definition
of eval-when-compile.  It's easy enough to see that this part is working
as advertised.

> Here, you're defining a macro at compilation time.  When compiling this
> file, the macro is known and (ewc-macro) expands to (defvar macro-nil
> "false") so that's compiled into the elc file, and that's the only thing
> that's loaded.

Yes, that is working as expected, however I don't like the clutter that
it produces.

> If you try to load the .el file directly, then the macro is not defined,
> and you're trying to call a function named (ewc-macro) which will fail.

Again, the macro will be defined at load time and expanded from the
`(ewc-macro)´ form.  There'd be a lot of broken code in Emacs if that
wasn't working.

> Now indeed, if you have decisions to make at compilation time, you need
> to define variables and functions at compilation time to compute those
> decisions.

What I'm actually trying to do is providing compatibility definitions
for other versions of Emacs.  That works fine as long as I only need to
compute different values at compile time (as documented in the manual).
It doesn't work when I can do a `(defalias …)´ for one version of Emacs,
but need a `(defun …)´ for another.  It can all be solved one way or the
other by adding macros to the mix, but my question still hasn't been
answered: why does it not work with eval-when-compile?


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

SD adaptation for Waldorf Blofeld V1.15B11:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27 17:50   ` eval-when-compile Achim Gratz
@ 2012-07-28  0:52     ` Stephen J. Turnbull
  2012-07-28  6:01       ` eval-when-compile Achim Gratz
  2012-07-28 18:04     ` eval-when-compile PJ Weisberg
  1 sibling, 1 reply; 10+ messages in thread
From: Stephen J. Turnbull @ 2012-07-28  0:52 UTC (permalink / raw)
  To: Achim Gratz; +Cc: emacs-devel

Achim Gratz writes:

 > What I'm actually trying to do is providing compatibility definitions
 > for other versions of Emacs.

Have you looked at the techniques used in APEL?



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-28  0:52     ` eval-when-compile Stephen J. Turnbull
@ 2012-07-28  6:01       ` Achim Gratz
  0 siblings, 0 replies; 10+ messages in thread
From: Achim Gratz @ 2012-07-28  6:01 UTC (permalink / raw)
  To: emacs-devel

Stephen J. Turnbull writes:
>  > What I'm actually trying to do is providing compatibility definitions
>  > for other versions of Emacs.
>
> Have you looked at the techniques used in APEL?

As I don't even knew it existed until now: no.  I#ll take a look when I
find the time.


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

Factory and User Sound Singles for Waldorf Blofeld:
http://Synth.Stromeko.net/Downloads.html#WaldorfSounds




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27 17:50   ` eval-when-compile Achim Gratz
  2012-07-28  0:52     ` eval-when-compile Stephen J. Turnbull
@ 2012-07-28 18:04     ` PJ Weisberg
  2012-08-08 18:51       ` eval-when-compile Achim Gratz
  1 sibling, 1 reply; 10+ messages in thread
From: PJ Weisberg @ 2012-07-28 18:04 UTC (permalink / raw)
  To: Achim Gratz; +Cc: emacs-devel

On Fri, Jul 27, 2012 at 10:50 AM, Achim Gratz <Stromeko@nexgo.de> wrote:
> Pascal J. Bourguignon writes:
>> C-h f eval-when-compile RET
>>
>>     Like `progn', but evaluates the body at compile time if you're compiling.
>>     Thus, the result of the body appears to the compiler as a quoted constant.
>>     In interpreted code, this is entirely equivalent to `progn'.
>>
>> What more can I add?
>
> I read that.  It doesn't seem to work that way or has some strings
> attached that aren't obvious to me from the documentation.
>
>> The above source will evaluate, when you compile the file:
>>
>>     (defvar unquoted-t "true")
>>     '(defvar quoted-nil "false")
>
> No.  They will evaluate to
>
> unquoted-t
> (defvar quoted-nil "false")
>
> The unquoted variant was only there to check if maybe there's another
> `(quote …)´ snuck in.  I expected the defvar form to compile, but it
> doesn't.

You missed this part:

     Thus, the result of the body appears to the compiler as a quoted constant.

So they really evaluate to:

'unquoted-t
'(defvar quoted-nil "false")

Which of course does nothing, so the compiler optimizes it away.

You know what you could do?

---
(eval
 (eval-when-compile
   (if nil
       '(defvar quoted-t "true")
     '(defvar quoted-nil "false")))
---

That'll compile to:

---
(eval
 '(defvar quoted-nil "false"))
---

-PJ

Gehm's Corollary to Clark's Law: Any technology distinguishable from
magic is insufficiently advanced.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-28 18:04     ` eval-when-compile PJ Weisberg
@ 2012-08-08 18:51       ` Achim Gratz
  0 siblings, 0 replies; 10+ messages in thread
From: Achim Gratz @ 2012-08-08 18:51 UTC (permalink / raw)
  To: emacs-devel

PJ Weisberg writes:
> You know what you could do?
>
> ---
> (eval
>  (eval-when-compile
>    (if nil
>        '(defvar quoted-t "true")
>      '(defvar quoted-nil "false")))
> ---
>
> That'll compile to:
>
> ---
> (eval
>  '(defvar quoted-nil "false"))
> ---

Thanks.  I tried this and actually it compiles to just

(defvar quoted-nil "false")

as I expected my first variant to do.  I am not sure what the outer eval
is doing, though: it doesn't look like it is executed at compile-time,
so it must somehow be optimized away by the byte-compiler (some rule
that "(eval (quote <…>))" is identical to "<…>", perhaps?).


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

SD adaptations for Waldorf Q V3.00R3 and Q+ V3.54R2:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: eval-when-compile
  2012-07-27  5:01 eval-when-compile Achim Gratz
  2012-07-27  6:26 ` eval-when-compile Pascal J. Bourguignon
@ 2012-08-08 21:13 ` Johan Bockgård
  1 sibling, 0 replies; 10+ messages in thread
From: Johan Bockgård @ 2012-08-08 21:13 UTC (permalink / raw)
  To: emacs-devel

Achim Gratz <Stromeko@nexgo.de> writes:

> I've been trying to use eval-when-compile to switch between alternate
> versions of code based on a compile-time decision.

    (if (eval-when-compile CONDITION)
        ...)



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-08-08 21:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-27  5:01 eval-when-compile Achim Gratz
2012-07-27  6:26 ` eval-when-compile Pascal J. Bourguignon
2012-07-27  7:41   ` eval-when-compile PJ Weisberg
2012-07-27  8:11     ` eval-when-compile Pascal J. Bourguignon
2012-07-27 17:50   ` eval-when-compile Achim Gratz
2012-07-28  0:52     ` eval-when-compile Stephen J. Turnbull
2012-07-28  6:01       ` eval-when-compile Achim Gratz
2012-07-28 18:04     ` eval-when-compile PJ Weisberg
2012-08-08 18:51       ` eval-when-compile Achim Gratz
2012-08-08 21:13 ` eval-when-compile Johan Bockgård

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.