From: Dan Muller
Subject: eval-when -- pls check my understanding
Date: 
Message-ID: <opjcd.8621$5b1.4311@newssvr17.news.prodigy.com>
Sorry to bring up another EVAL-WHEN question, but I want to make sure
I got this right.

Why does this compile:

  (eval-when (:load-toplevel :execute :compile-toplevel)
    #-:asdf (load "../cl-library/asdf"))
  (print asdf:*central-registry*)

But this does not:

  (eval-when (:load-toplevel :execute :compile-toplevel)
    #-:asdf (load "../cl-library/asdf")
    (print asdf:*central-registry*))

The second version fails during compilation, saying that package ASDF
was not found.

I think it fails because the entire eval-when form has to be processed
by the reader before the compiler can even begin to see the LOAD
form. Is that correct? It seems simple, but it had me stumped for
quite a while. I spent much of today trying to write some simple
loader/configuration files that had a lot of stuff like this in them,
and it was driving me nuts.

I also spent a lot of time staring at that table in section 3.2.3.1 of
the Hyperspec.  I'm considering having it tatooed on me somewhere for
reference, even though this particular problem ended up having nothing
to do with it.

From: Pascal Bourguignon
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <87k6tq6s5f.fsf@thalassa.informatimago.com>
Dan Muller <·········@sneakemail.com> writes:

> Sorry to bring up another EVAL-WHEN question, but I want to make sure
> I got this right.
> 
> Why does this compile:
> 
>   (eval-when (:load-toplevel :execute :compile-toplevel)
>     #-:asdf (load "../cl-library/asdf"))
>   (print asdf:*central-registry*)
> 
> But this does not:
> 
>   (eval-when (:load-toplevel :execute :compile-toplevel)
>     #-:asdf (load "../cl-library/asdf")
>     (print asdf:*central-registry*))
> 
> The second version fails during compilation, saying that package ASDF
> was not found.
> 
> I think it fails because the entire eval-when form has to be processed
> by the reader before the compiler can even begin to see the LOAD
> form. Is that correct? It seems simple, but it had me stumped for
> quite a while. I spent much of today trying to write some simple
> loader/configuration files that had a lot of stuff like this in them,
> and it was driving me nuts.

That's right.  To write something equivalent to what you want to do in
the second form you'd have to write two eval-when:

   (eval-when (:load-toplevel :execute :compile-toplevel)
     #-:asdf (load "../cl-library/asdf"))
   (eval-when (:load-toplevel :execute :compile-toplevel)
     (print asdf:*central-registry*))

 
> I also spent a lot of time staring at that table in section 3.2.3.1 of
> the Hyperspec.  I'm considering having it tatooed on me somewhere for
> reference, even though this particular problem ended up having nothing
> to do with it.

I'm still trying to understand it...


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Voting Democrat or Republican is like choosing a cabin in the Titanic.
From: Barry Margolin
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <barmar-225ECF.03051117102004@comcast.dca.giganews.com>
In article <··············@thalassa.informatimago.com>,
 Pascal Bourguignon <····@mouse-potato.com> wrote:

> Dan Muller <·········@sneakemail.com> writes:
> 
> > Sorry to bring up another EVAL-WHEN question, but I want to make sure
> > I got this right.
> > 
> > Why does this compile:
> > 
> >   (eval-when (:load-toplevel :execute :compile-toplevel)
> >     #-:asdf (load "../cl-library/asdf"))
> >   (print asdf:*central-registry*)
> > 
> > But this does not:
> > 
> >   (eval-when (:load-toplevel :execute :compile-toplevel)
> >     #-:asdf (load "../cl-library/asdf")
> >     (print asdf:*central-registry*))
> > 
> > The second version fails during compilation, saying that package ASDF
> > was not found.
> > 
> > I think it fails because the entire eval-when form has to be processed
> > by the reader before the compiler can even begin to see the LOAD
> > form. Is that correct? It seems simple, but it had me stumped for
> > quite a while. I spent much of today trying to write some simple
> > loader/configuration files that had a lot of stuff like this in them,
> > and it was driving me nuts.
> 
> That's right.  To write something equivalent to what you want to do in
> the second form you'd have to write two eval-when:
> 
>    (eval-when (:load-toplevel :execute :compile-toplevel)
>      #-:asdf (load "../cl-library/asdf"))
>    (eval-when (:load-toplevel :execute :compile-toplevel)
>      (print asdf:*central-registry*))

It can be done in one EVAL-WHEN, but it's a bit gross:

(eval-when (:load-toplevel :execute :compile-toplevel)
  #-:asdf (load "../cl-library/asdf")
  (print (symbol-value (intern :*central-registry* :asdf))))

Using INTERN explicitly delays the access of the package until the 
expression is being executed.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Dan Muller
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <0ttcd.18198$Qv5.764@newssvr33.news.prodigy.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <··············@thalassa.informatimago.com>,
>  Pascal Bourguignon <····@mouse-potato.com> wrote:
>
>> Dan Muller <·········@sneakemail.com> writes:
>> 
>> > Sorry to bring up another EVAL-WHEN question, but I want to make sure
>> > I got this right.
>> > 
>> > ...
>> 
>> That's right.  ...

> It can be done in one EVAL-WHEN, but it's a bit gross:
>
> (eval-when (:load-toplevel :execute :compile-toplevel)
>   #-:asdf (load "../cl-library/asdf")
>   (print (symbol-value (intern :*central-registry* :asdf))))
>
> Using INTERN explicitly delays the access of the package until the 
> expression is being executed.
>

You're right, that's gross, but clever. Thanks!
From: Douglas Philips
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <4173bea6_1@news.nauticom.net>
On 2004-10-17 08:21:16 -0400, Dan Muller <·········@sneakemail.com> said:
> Barry Margolin <······@alum.mit.edu> writes:
>> It can be done in one EVAL-WHEN, but it's a bit gross:
>> 
>> (eval-when (:load-toplevel :execute :compile-toplevel)
>> #-:asdf (load "../cl-library/asdf")
>> (print (symbol-value (intern :*central-registry* :asdf))))
>> 
>> Using INTERN explicitly delays the access of the package until the 
>> expression is being executed.
>> 
> 
> You're right, that's gross, but clever. Thanks!

Step away from the parens keys... nice'n'slow... and no one will get sick.

<D\'gou
From: Dan Muller
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <Kytcd.18200$Qv5.15741@newssvr33.news.prodigy.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Dan Muller <·········@sneakemail.com> writes:
>
>> Sorry to bring up another EVAL-WHEN question, but I want to make sure
>> I got this right.
>> ...
>
> That's right.  To write something equivalent to what you want to do in
> the second form you'd have to write two eval-when:
>
>    (eval-when (:load-toplevel :execute :compile-toplevel)
>      #-:asdf (load "../cl-library/asdf"))
>    (eval-when (:load-toplevel :execute :compile-toplevel)
>      (print asdf:*central-registry*))
>

Thanks for the confirmation. Yeah, I realized that another eval-when
was necessary to get exactly the same behavior.

>  
>> I also spent a lot of time staring at that table in section 3.2.3.1 of
>> the Hyperspec.  I'm considering having it tatooed on me somewhere for
>> reference, even though this particular problem ended up having nothing
>> to do with it.
>
> I'm still trying to understand it...

I can't help but think that some sort of graphical representation of
the interaction and information flow between the compiler, the loader,
and the various environments would help to visualize this stuff.


> -- 
> __Pascal Bourguignon__                     http://www.informatimago.com/
>
> Voting Democrat or Republican is like choosing a cabin in the Titanic.

OT: Indeed! Have you read some of the critiques of the voting systems
that lead to this bipartisan non-choice? There are some interesting
links on http://www.spookydistance.com/cgi-bin/public-wiki.pl?Politics,
under "Running elections".
From: Steven E. Harris
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <jk4is98dnpt.fsf@W003275.na.alarismed.com>
Dan Muller <·········@sneakemail.com> writes:

> Sorry to bring up another EVAL-WHEN question, but I want to make
> sure I got this right.

Similarly, I've never been able to get this one to work right:

(eval-when (:execute :load-toplevel :compile-toplevel)
  #-:asdf
  (load (mk-relpath +lib-root+
                    :directory '(:relative "asdf") :name "asdf")))

(pushnew (mk-relpath +lib-root+ :directory '(:relative "systems")) asdf:*central-registry*
         :test #'equal)
(pushnew (make-pathname :directory '(:relative)) asdf:*central-registry*
         :test #'equal)


Assume that mk-relpath and +lib-root+ are a function and constant
defined previously.

My goal is to have this file be compilable, as it's in my ~/.clisprc
file. Each time I start CLISP, I want ASDF loaded, unless it has
already been loaded by way of starting from some saved image. I don't
really need ASDF loaded at compile-time, but failing to load it then
seems to keep the two pushnew forms from compiling, for they make
reference to asdf:*central-registry*.

The form as shown above compiles, and ASDF does get loaded each time I
start CLISP. But if I forcibly execute

  (load "~/.clisprc")

at the REPL in a running CLISP that already has :ASDF in *features*,
ASDF gets loaded again anyway. It seems as though the #-:asdf guard is
perhaps looking at some /other/ *features* set when it gets loaded.

Flailing some more, note that evaluating

  (eval-when (:execute)
    #-:asdf (write-line "not defined")
    #+:asdf 42)

in the same REPL yields 42.

How can I ensure that ASDF is only loaded if it has not already been
loaded? Is it truly necessary to load ASDF in order to include any
forms that mention asdf:*central-registry* in a compiled file, even if
those forms are not to run until, well, run-time?

-- 
Steven E. Harris
From: ·········@random-state.net
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <cl2s7k$cgalq$1@midnight.cs.hut.fi>
Steven E. Harris <···@panix.com> wrote:

> Similarly, I've never been able to get this one to work right:

 ...snipped EVAL-WHEN...

This is not an EVAL-WHEN issue, but a reader issue. When lips is
confronted with a form looking like

 (... (load-foo) ... foo:bar ...)

it will read the _whole_ form in before executing any of it (barring
#. in there), and reading FOO:BAR means interning BAR in the package FOO
-- which isn't loaded yet.

You must either

 1. Put the loading form into a different toplevel form, so that
    it will be executed before the previous one is read.

 2. Load FOO at read-time, using #.

 3. Intern BAR in FOO at runtime, eg. (funcall (intern "FOO" :bar)),
    (symbol-value (intern "FOO" :bar)), etc.

> loaded? Is it truly necessary to load ASDF in order to include any
> forms that mention asdf:*central-registry* in a compiled file, even if

Yes, and hopefully the reason is clear now: you must have the package in
order to intern the symbol.

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Steven E. Harris
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <jk43c0aem5m.fsf@W003275.na.alarismed.com>
·········@random-state.net writes:

> This is not an EVAL-WHEN issue, but a reader issue.

Understood.

But what about the feature test expression? I find that if I compile a
file (~/.clisprc.lisp) with either

  #-:asdf
  (eval-when (:execute :load-toplevel :compile-toplevel)
    (load +asdf-path+))

or

  (eval-when (:execute :load-toplevel :compile-toplevel)
    #-:asdf
    (load +asdf-path+))

then the resultant compiled file causes ASDF to be loaded both the
first time and every subsequent time the same file is loaded. That is,
if I start CLISP, ASDF gets loaded, but if I reload ~/.clisprc, ASDF
gets loaded again, even though :ASDF is in *features*.

My interpretation of this behavior is that the feature test is getting
consumed at compile-time. When the file is compiled, the :ASDF feature
test fails, so the subsequent load form is included unconditionally in
the compiled file.

Should I be writing something more like

  (eval-when (:execute :load-toplevel :compile-toplevel)
    (unless (member :asdf *features*)
      (load +asdf-path+)))

That seems to do the trick, but I'm not sure it's the right way.

-- 
Steven E. Harris
From: Peter Seibel
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <m38ya2hdnv.fsf@javamonkey.com>
"Steven E. Harris" <···@panix.com> writes:

> ·········@random-state.net writes:
>
>> This is not an EVAL-WHEN issue, but a reader issue.
>
> Understood.
>
> But what about the feature test expression? I find that if I compile a
> file (~/.clisprc.lisp) with either
>
>   #-:asdf
>   (eval-when (:execute :load-toplevel :compile-toplevel)
>     (load +asdf-path+))
>
> or
>
>   (eval-when (:execute :load-toplevel :compile-toplevel)
>     #-:asdf
>     (load +asdf-path+))
>
> then the resultant compiled file causes ASDF to be loaded both the
> first time and every subsequent time the same file is loaded. That is,
> if I start CLISP, ASDF gets loaded, but if I reload ~/.clisprc, ASDF
> gets loaded again, even though :ASDF is in *features*.
>
> My interpretation of this behavior is that the feature test is
> getting consumed at compile-time.

Read-time. The file-compiler, while reading the file, sees that :asdf
is not in *features* so, reads the form and generates code for it.
After that it doesn't matter what happens to *features* later; the
compiled file contains the code to do the (load +asdf-path+).

> When the file is compiled, the :ASDF feature test fails, so the
> subsequent load form is included unconditionally in the compiled
> file.

Yes.

> Should I be writing something more like
>
>   (eval-when (:execute :load-toplevel :compile-toplevel)
>     (unless (member :asdf *features*)
>       (load +asdf-path+)))
>
> That seems to do the trick, but I'm not sure it's the right way.

Dunno if that's idiomatic or not but it seems reasonable.

-Peter

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

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Dan Muller
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <NSidd.11052$Rf1.2568@newssvr19.news.prodigy.com>
Peter Seibel <·····@javamonkey.com> writes:

> "Steven E. Harris" <···@panix.com> writes:
>
>> ·········@random-state.net writes:
>>
>>> This is not an EVAL-WHEN issue, but a reader issue.
>>
>> Understood.
>>
>> But what about the feature test expression? I find that if I compile a
>> file (~/.clisprc.lisp) with either
>>
>>   #-:asdf
>>   (eval-when (:execute :load-toplevel :compile-toplevel)
>>     (load +asdf-path+))
>>
>> or
>>
>>   (eval-when (:execute :load-toplevel :compile-toplevel)
>>     #-:asdf
>>     (load +asdf-path+))
>>
>> then the resultant compiled file causes ASDF to be loaded both the
>> first time and every subsequent time the same file is loaded. That is,
>> if I start CLISP, ASDF gets loaded, but if I reload ~/.clisprc, ASDF
>> gets loaded again, even though :ASDF is in *features*.
>>
>> My interpretation of this behavior is that the feature test is
>> getting consumed at compile-time.
>
> Read-time. The file-compiler, while reading the file, sees that :asdf
> is not in *features* so, reads the form and generates code for it.
> After that it doesn't matter what happens to *features* later; the
> compiled file contains the code to do the (load +asdf-path+).
>
>> When the file is compiled, the :ASDF feature test fails, so the
>> subsequent load form is included unconditionally in the compiled
>> file.
>
> Yes.
>
>> Should I be writing something more like
>>
>>   (eval-when (:execute :load-toplevel :compile-toplevel)
>>     (unless (member :asdf *features*)
>>       (load +asdf-path+)))
>>
>> That seems to do the trick, but I'm not sure it's the right way.
>
> Dunno if that's idiomatic or not but it seems reasonable.

This is good! I hadn't thought of this issue, and it no doubt was also
contributing to my confusion.

In theory, I understand how the reader/compiler/loader things
relate. But apparently I haven't completely internalized it yet,
otherwise this stuff would seem obvious right off the bat.

For your amusement: Another thing that confused me while struggling
with this was that I was sorting the feature list at the REPL in order
to more easily inspect it. I didn't realize, however, that SORT is
mutating -- so I kept mangling my feature list, and thinking that it
was the code I was loading that somehow misbehaving. Doh!
From: Thomas A. Russ
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <ymi1xfq9ulu.fsf@sevak.isi.edu>
Dan Muller <·········@sneakemail.com> writes:

> For your amusement: Another thing that confused me while struggling
> with this was that I was sorting the feature list at the REPL in order
> to more easily inspect it. I didn't realize, however, that SORT is
> mutating -- so I kept mangling my feature list, and thinking that it
> was the code I was loading that somehow misbehaving. Doh!

This is a rather common booby trap in the language.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Thomas A. Russ
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <ymizn2e8g0x.fsf@sevak.isi.edu>
Dan Muller <·········@sneakemail.com> writes:

> For your amusement: Another thing that confused me while struggling
> with this was that I was sorting the feature list at the REPL in order
> to more easily inspect it. I didn't realize, however, that SORT is
> mutating -- so I kept mangling my feature list, and thinking that it
> was the code I was loading that somehow misbehaving. Doh!

This is a rather common booby trap in the language, so you
have lots of company....

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ·········@random-state.net
Subject: Re: eval-when -- pls check my understanding
Date: 
Message-ID: <cl5i5i$cos6c$1@midnight.cs.hut.fi>
Steven E. Harris <···@panix.com> wrote:

> My interpretation of this behavior is that the feature test is getting
> consumed at compile-time. When the file is compiled, the :ASDF feature

At read-time. #- and #+ are reader-macros, and compiling a file includes
reading it, so the fasl will not contain the conditionals anymore: its
contents are determined by the conditionals.

Don't compile the file, or use MEMBER as you noticed.

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."