Re: Reading a file at compilation
Camille Troillard <camille@osculator.net> writes:
> I am sure this is a very basic question, but I can't find the good way
> to do this correctly:
>
> I would like to load a small database of items stored in a text file
> at compile time. Here is basically what I would like to do:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
> (defconstant +collection+
No, you don't want that. defconstant tells to the compiler that he can
inline the data in the object code. If you load the data again when you
load the object code (assuming it's not a single number, symbol or
character), then you will have two different copies of the data (not
eql), and therefore you will have lied to the compiler.
> (make-collection
> (with-open-file (stream #P"collection.txt" :direction :input)
> (read stream)))))
>
>
> Where #P"collection.txt" is in the same directory as the file
> compiled.
What about when the source file is loaded (:execute), or when the
compiled file is loaded (:load-toplevel)? Is/Will the collection.txt
file be in the same directory?
> I am using ASDF to build my system, but would like to be
> able to build +collection+ from the LispWorks Editor as well.
>
> I tried to play with (hcl:cd) and (merge-pathnames) without success.
(merge-pathnames #P"collection.txt" :defaults *load-pathname*)
But *load-pathname* is set only when there's a file being LOADed. It
won't work for example if you save an executable image.
> Can this be done?
Yes.
> Can anyone point me the right direction?
If the collection object itself can be written to a file, (eg. it's not
a closure), then you could just load it at read time, and let the
compiler write it to the fasl file, and let it reload it from the fasl
file at load time. If the collection is a CLOS object (or contains CLOS
objects), then you can define a MAKE-LOAD-FORM method.
(defvar *collection*
'#.(make-collection
(with-open-file (stream #P"RESOURCES:COLLECTION.TXT" :direction :input)
(read stream))))
Now, if you want to be able to change the collection "at run time", that
is, when you launch the program, instead of having it hard wired in the
executable, the best would be to load it explicitely when you initialize
the application (from the "main" function), since eval-when bodies won't
be evaluated when you start it from a saved image.
I would use logical pathnames to abstract away the problem of the path
(foremost if the application has other resources to load at run-time).
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.