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
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 ***
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
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
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.
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
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.
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
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.
···@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.