From: Peter Seibel
Subject: eval-when :load-toplevel :execute
Date: 
Message-ID: <m3y8ira5zv.fsf@javamonkey.com>
Is there ever a reason to wrap a top-level from in

  (eval-when (:load-toplevel :execute) ...)

? Here are the relevant rows from Figure 3-7 in 3.2.3.1 describing how
such a form is processed as a top-level form:

  CT   LT   E    Mode  Action    New Mode          
  ----------
  No   Yes  Yes  CTT   Process   compile-time-too  
  No   Yes  Yes  NCT   Process   not-compile-time  

So, whatever mode we are in the body will be processed as top-level
forms in the same mode. So it seems that we could have just as well
made the body forms top-level forms without the EVAL-WHEN and gotten
the same result, no?

And if the EVAL-WHEN appears in a non-top-level position it is simply
treated as PROGN.

For a more concrete example, suppose I have a macro like this:

  (defmacro define-url-function (name (request &rest params) &body body)
    `(progn
       (eval-when (:load-toplevel :execute)
         (publish :path ,(format nil "/~(~a~)" name) :function ',name))
       (defun ,name (,request) ...)))

Is there any reason not to write that as:

  (defmacro define-url-function (name (request &rest params) &body body)
    `(progn
       (publish :path ,(format nil "/~(~a~)" name) :function ',name))
       (defun ,name (,request) ...))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp

From: Barry Margolin
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <barmar-F6CAB2.19342230092004@comcast.dca.giganews.com>
In article <··············@javamonkey.com>,
 Peter Seibel <·····@javamonkey.com> wrote:

> Is there ever a reason to wrap a top-level from in
> 
>   (eval-when (:load-toplevel :execute) ...)
> 
> ? Here are the relevant rows from Figure 3-7 in 3.2.3.1 describing how
> such a form is processed as a top-level form:
> 
>   CT   LT   E    Mode  Action    New Mode          
>   ----------
>   No   Yes  Yes  CTT   Process   compile-time-too  
>   No   Yes  Yes  NCT   Process   not-compile-time  
> 
> So, whatever mode we are in the body will be processed as top-level
> forms in the same mode. So it seems that we could have just as well
> made the body forms top-level forms without the EVAL-WHEN and gotten
> the same result, no?
> 
> And if the EVAL-WHEN appears in a non-top-level position it is simply
> treated as PROGN.

Correct.  (:load-toplevel :execute) is the way forms are normally 
processed, so you're just asking for the default explicitly.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Peter Seibel
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <m3oejm8gqv.fsf@javamonkey.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <··············@javamonkey.com>,
>  Peter Seibel <·····@javamonkey.com> wrote:
>
>> Is there ever a reason to wrap a top-level from in
>> 
>>   (eval-when (:load-toplevel :execute) ...)
>> 
>> ? Here are the relevant rows from Figure 3-7 in 3.2.3.1 describing how
>> such a form is processed as a top-level form:
>> 
>>   CT   LT   E    Mode  Action    New Mode          
>>   ----------
>>   No   Yes  Yes  CTT   Process   compile-time-too  
>>   No   Yes  Yes  NCT   Process   not-compile-time  
>> 
>> So, whatever mode we are in the body will be processed as top-level
>> forms in the same mode. So it seems that we could have just as well
>> made the body forms top-level forms without the EVAL-WHEN and gotten
>> the same result, no?
>> 
>> And if the EVAL-WHEN appears in a non-top-level position it is simply
>> treated as PROGN.
>
> Correct.  (:load-toplevel :execute) is the way forms are normally 
> processed, so you're just asking for the default explicitly.

So is it considered good style to do so? Or to look at it another way,
it seems like you might sometimes use:

  (eval-when (:compile-toplevel) ...)

for code you only want to run at compile time. And you might use:

  (eval-when (:compile-toplevel :load-toplevel :execute) ...)

for code you want to run at both compile time and "regularly". Is
there any other combination that is actually useful?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Duane Rettig
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <4lleq5myz.fsf@franz.com>
Peter Seibel <·····@javamonkey.com> writes:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > In article <··············@javamonkey.com>,
> >  Peter Seibel <·····@javamonkey.com> wrote:
> >
> >> Is there ever a reason to wrap a top-level from in
> >> 
> >>   (eval-when (:load-toplevel :execute) ...)
> >> 
> >> ? Here are the relevant rows from Figure 3-7 in 3.2.3.1 describing how
> >> such a form is processed as a top-level form:
> >> 
> >>   CT   LT   E    Mode  Action    New Mode          
> >>   ----------
> >>   No   Yes  Yes  CTT   Process   compile-time-too  
> >>   No   Yes  Yes  NCT   Process   not-compile-time  
> >> 
> >> So, whatever mode we are in the body will be processed as top-level
> >> forms in the same mode. So it seems that we could have just as well
> >> made the body forms top-level forms without the EVAL-WHEN and gotten
> >> the same result, no?
> >> 
> >> And if the EVAL-WHEN appears in a non-top-level position it is simply
> >> treated as PROGN.
> >
> > Correct.  (:load-toplevel :execute) is the way forms are normally 
> > processed, so you're just asking for the default explicitly.
> 
> So is it considered good style to do so? Or to look at it another way,
> it seems like you might sometimes use:
> 
>   (eval-when (:compile-toplevel) ...)
> 
> for code you only want to run at compile time. And you might use:
> 
>   (eval-when (:compile-toplevel :load-toplevel :execute) ...)
> 
> for code you want to run at both compile time and "regularly". Is
> there any other combination that is actually useful?

I sometimes use the combination

(eval-when (:compile-toplevel :execute) ...)

when I don't want the space expense of one-use definitions that
have been used during the compilation of the file, but when I also
want the option of loading the source file uncompiled.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Vassil Nikolov
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <lzoejkhicu.fsf@janus.vassil.nikolov.names>
Duane Rettig <·····@franz.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
> [...]
>> it seems like you might sometimes use:
>> 
>>   (eval-when (:compile-toplevel) ...)
>> 
>> for code you only want to run at compile time. And you might use:
>> 
>>   (eval-when (:compile-toplevel :load-toplevel :execute) ...)
>> 
>> for code you want to run at both compile time and "regularly". Is
>> there any other combination that is actually useful?
>
> I sometimes use the combination
>
> (eval-when (:compile-toplevel :execute) ...)
>
> when I don't want the space expense of one-use definitions that
> have been used during the compilation of the file, but when I also
> want the option of loading the source file uncompiled.

  Would the following be another valid example: part of a definition
  macro's expansion being (EVAL-WHEN (:EXECUTE) ...) to capture the
  source file of a defined something for future reference?  (For
  example, to be able to take the user to that source file.)

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Peter Seibel
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <m3r7ogskpn.fsf@javamonkey.com>
Vassil Nikolov <········@poboxes.com> writes:

> Duane Rettig <·····@franz.com> writes:
>
>> Peter Seibel <·····@javamonkey.com> writes:
>> [...]
>>> it seems like you might sometimes use:
>>> 
>>>   (eval-when (:compile-toplevel) ...)
>>> 
>>> for code you only want to run at compile time. And you might use:
>>> 
>>>   (eval-when (:compile-toplevel :load-toplevel :execute) ...)
>>> 
>>> for code you want to run at both compile time and "regularly". Is
>>> there any other combination that is actually useful?
>>
>> I sometimes use the combination
>>
>> (eval-when (:compile-toplevel :execute) ...)
>>
>> when I don't want the space expense of one-use definitions that
>> have been used during the compilation of the file, but when I also
>> want the option of loading the source file uncompiled.
>
>   Would the following be another valid example: part of a definition
>   macro's expansion being (EVAL-WHEN (:EXECUTE) ...) to capture the
>   source file of a defined something for future reference?  (For
>   example, to be able to take the user to that source file.)

Only if you don't want the code so wrapped to be executed when the
definitional macro appears as a top-level form. I.e. if you have:

  (defmacro deffoo (name (&rest args) &body body)
    `(progn
      (eval-when (:execute)
        (record-source-location 'foo ',name))
      ...))

then the record-source-location expression will only will be evaluated
when deffoo is used in non-top-level positions (or when a call to
DEFFOO is directly wrapped in an EVAL-WHEN with :compile-toplevel). If
you have a file that contains a deffoo at the top-level you will not
record the source location either when the file is compiled (probably
okay) nor when it is loaded (probably not what you want.)

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Vassil Nikolov
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <lz1xgfzo68.fsf@janus.vassil.nikolov.names>
Peter Seibel <·····@javamonkey.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
> [...]
>>   Would the following be another valid example: part of a definition
>>   macro's expansion being (EVAL-WHEN (:EXECUTE) ...) to capture the
>>   source file of a defined something for future reference?  (For
>>   example, to be able to take the user to that source file.)
>
> Only if you don't want the code so wrapped to be executed when the
> definitional macro appears as a top-level form.

  ...in a compiled file being loaded.  But I want it to be executed
  when the definition appears as a top-level form in a source file
  being executed, and it will.

> I.e. if you have:
>
>   (defmacro deffoo (name (&rest args) &body body)
>     `(progn
>       (eval-when (:execute)
>         (record-source-location 'foo ',name))
>       ...))
>
> then the record-source-location expression will only will be evaluated
> when deffoo is used in non-top-level positions

  ...or when DEFFOO is used in a top-level position in a source file
  being executed...

> (or when a call to
> DEFFOO is directly wrapped in an EVAL-WHEN with :compile-toplevel).

  Just having :COMPILE-TOPLEVEL in a wrapping EVAL-WHEN won't have it
  executed, since

   (eval-when (:compile-toplevel)
     (eval-when (:execute) ...))

  is a no-op when either executing a source file or loading a compiled
  file.

> If
> you have a file that contains a deffoo at the top-level you will not
> record the source location either when the file is compiled (probably
> okay) nor when it is loaded (probably not what you want.)

  For this example, I want the source location recorded only when a
  source file is executed, but not when a compiled file is loaded.

  (It is a good idea to record the source location of compiled files
  as well, of course, but I want to treat the latter case separately
  since the assumption that the source is available at run-time is
  distinctly less justified with compiled files.)

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Peter Seibel
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <m3y8inr4e2.fsf@javamonkey.com>
Vassil Nikolov <········@poboxes.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> Vassil Nikolov <········@poboxes.com> writes:
>> [...]
>>>   Would the following be another valid example: part of a definition
>>>   macro's expansion being (EVAL-WHEN (:EXECUTE) ...) to capture the
>>>   source file of a defined something for future reference?  (For
>>>   example, to be able to take the user to that source file.)
>>
>> Only if you don't want the code so wrapped to be executed when the
>> definitional macro appears as a top-level form.
>
>   ...in a compiled file being loaded.  But I want it to be executed
>   when the definition appears as a top-level form in a source file
>   being executed, and it will.

Ah, good point. Though presumably one wants to use this capability
with some taste--making files where (load "foo.lisp") has a noticably
differently effect than (load (compile-file "foo.lisp")) is probably
not the best way to avoid total confusion down the line. (I'm sure
*you* always program tastefully; this caveat is meant by way of,
"Kids, don't try this at home; these are trained professionals.")

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Thomas F. Burdick
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <xcvbrfj7j36.fsf@conquest.OCF.Berkeley.EDU>
Barry Margolin <······@alum.mit.edu> writes:

> In article <··············@javamonkey.com>,
>  Peter Seibel <·····@javamonkey.com> wrote:
>
> > And if the EVAL-WHEN appears in a non-top-level position it is simply
> > treated as PROGN.
> 
> Correct.  (:load-toplevel :execute) is the way forms are normally 
> processed, so you're just asking for the default explicitly.

Which, IMO, can make your macros clearer.  One other implication of
this is that you can use eval-when (:load-toplevel :execute) to turn
off the compile-time effects of a form.  Eg:

  (defmacro foo (...)
    `(progn (eval-when (:compile-toplevel) ...)
            (eval-when (:load-toplevel :execute) ...)))

  (defmacro bar (...)
    `(progn (eval-when (:load-toplevel :execute)
              (foo ...))))

The eval-when in bar prevents foo from doing the work it normally
would at compile-time.  You could of course have this effect by
wrapping the call to foo in any form that makes it non-toplevel, but I
like eval-when for this effect, because it spells out the times you're
referring to explicitly.
From: Kalle Olavi Niemitalo
Subject: Re: eval-when :load-toplevel :execute
Date: 
Message-ID: <87hdpbh65g.fsf@Astalo.kon.iki.fi>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

>   (defmacro foo (...)
>     `(progn (eval-when (:compile-toplevel) ...)
>             (eval-when (:load-toplevel :execute) ...)))
>
>   (defmacro bar (...)
>     `(progn (eval-when (:load-toplevel :execute)
>               (foo ...))))
>
> The eval-when in bar prevents foo from doing the work it normally
> would at compile-time.

Does this really work?  Suppose a file containing (bar ...) is
compiled.  Here is the process according to CLHS section 3.2.3.1:

- (bar ...) is a top-level form to be processed in not-compile-time
  mode.  It is a macro form.  The expansion is...

- (progn (eval-when (:load-toplevel :execute) (foo ...))), which
  is also processed in not-compile-time mode.  It is a progn form;
  the body forms are processed sequentially.  The only one is...

- (eval-when (:load-toplevel :execute) (foo ...)), which is also
  processed in not-compile-time mode.  From the table:
  Action=Process, New Mode=not-compile-time.

- (foo ...) is processed in not-compile-time mode.  It is a
  macro form.  The expansion is...

- (progn (eval-when (:compile-toplevel) ...) (eval-when
  (:load-toplevel :execute) ...)), which is processed in
  not-compile-time mode.  It is a progn form; the body forms are
  processed sequentially.  I'll focus on the first one:

- (eval-when (:compile-toplevel) ...) is processed in
  not-compile-time mode.  From the table: Action=Evaluate,
  New Mode=---.

- ... is evaluated at compile time.

So the eval-when in BAR did not do anything useful.

> You could of course have this effect by wrapping the call to
> foo in any form that makes it non-toplevel, [...}

That would work.