From: Stormcoder
Subject: Loading a config file at run time
Date: 
Message-ID: <1146609129.486396.166130@e56g2000cwe.googlegroups.com>
I have an app that needs to load a configuration file at run time. The
config file is just a seperate lisp file. I need it to load at run
time. Currently I use (eval (load "config.lisp")).

Is there a better way to do this? I know the FAQs say that if you think
you need to use eval your probably wrong. So is there a better way to
do a run time config file or similar? There are to many options for
passing params at the command line.

From: Bill Atkins
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <87k694oxv5.fsf@rpi.edu>
"Stormcoder" <·········@gmail.com> writes:

> I have an app that needs to load a configuration file at run time. The
> config file is just a seperate lisp file. I need it to load at run
> time. Currently I use (eval (load "config.lisp")).
>
> Is there a better way to do this? I know the FAQs say that if you think
> you need to use eval your probably wrong. So is there a better way to
> do a run time config file or similar? There are to many options for
> passing params at the command line.
>

Drop the EVAL and you're set:

  (load "configfile.lisp")

-- 
This is a song that took me ten years to live and two years to write.
 - Bob Dylan
From: Ari Johnson
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <m2fyjs2fqa.fsf@hermes.theari.com>
Bill Atkins <············@rpi.edu> writes:

> "Stormcoder" <·········@gmail.com> writes:
>
>> I have an app that needs to load a configuration file at run time. The
>> config file is just a seperate lisp file. I need it to load at run
>> time. Currently I use (eval (load "config.lisp")).
>>
>> Is there a better way to do this? I know the FAQs say that if you think
>> you need to use eval your probably wrong. So is there a better way to
>> do a run time config file or similar? There are to many options for
>> passing params at the command line.
>>
>
> Drop the EVAL and you're set:
>
>   (load "configfile.lisp")

You still end up implicitly evaluating the contents of the file, but
at least you aren't explicitly calling #'eval this way.  Depending on
your configuration file, you may be able to avoid even the implicit
evaluation, though.

If you just dump an assoc-list to the configuration file, such that its
contents look like the following, then you can use the functions below
to read and write it (note that you can use something other than strings
for the configuration keys; just use #'assoc to access them):

(("port" . 8080) ("hostname" . "localhost"))

Functions:

(defun read-conf (filename)
  (with-open-file (s (merge-pathnames filename)
                     :direction :input
                     :if-does-not-exist nil)
    (and s (read s))))

(defun write-conf (filename config)
  (with-open-file (s (merge-pathnames filename)
                     :direction :output :if-exists :supersede)
    (write config :stream s :readably t)))
From: Stormcoder
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <1146678990.540717.167190@v46g2000cwv.googlegroups.com>
Read will create the symbols? Will the symbols be in the current
package or the user package?
From: Ari Johnson
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <m2r73b0z0r.fsf@hermes.theari.com>
"Stormcoder" <·········@gmail.com> writes:

> Read will create the symbols? Will the symbols be in the current
> package or the user package?

The sample configuration I gave you did not have any symbols.
Experiment a bit and see what you come up with. :)
From: Stormcoder
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <1146678353.000342.60260@y43g2000cwc.googlegroups.com>
As I understand it, load takes place at read time, not run time. The
intent of the eval is so that load is executed at run time. Being a
novice, I could be wrong.
From: Bill Atkins
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <87bqufxaoe.fsf@rpi.edu>
"Stormcoder" <·········@gmail.com> writes:

> As I understand it, load takes place at read time, not run time. The
> intent of the eval is so that load is executed at run time. Being a
> novice, I could be wrong.
>

You understand it incorrectly. :) LOAD is just a function; it is
evaluated at execution-time.

-- 
This is a song that took me ten years to live and two years to write.
 - Bob Dylan
From: Stormcoder
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <1146679650.550036.160140@i40g2000cwc.googlegroups.com>
So if I run load from within my entry point function it will be run at
run time? I have the symbols from the config file defvar'ed as special
variables in the main application source. When load is run from a
function, will the values from the config file show up in the special
variables I have defined?

So in the main program I have a bunch of these:
(defvar SCRIPTSDIR "")
(defvar ICONPATH "")
...

In my config file I have:
(setf SCRIPTSDIR "/......")
(setf ICONPATH "/......")
...

Should that work as expected?
From: Kalle Olavi Niemitalo
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <87vesmvrrk.fsf@Astalo.kon.iki.fi>
"Stormcoder" <·········@gmail.com> writes:

> So in the main program I have a bunch of these:
> (defvar SCRIPTSDIR "")
> (defvar ICONPATH "")
> ...
>
> In my config file I have:
> (setf SCRIPTSDIR "/......")
> (setf ICONPATH "/......")
> ...
>
> Should that work as expected?

If the current package is the same and the readtables are similar
enough, then it should work.  You can of course do 

  (let ((*package* '#.*package*))
    (load "config.file"))

to ensure that the current package is the same when "config.file"
is loaded as when the code doing the loading was read.  If this
is in a library, you might also consider WITH-STANDARD-IO-SYNTAX.

It would be customary to put *asterisks* around the names of your
special variables, and dashes between words:

  (defvar *SCRIPTS-DIR* "")
  (defvar *ICON-PATH* "")

Also, it might be a good idea (or perhaps not) to make
*SCRIPTS-DIR* a pathname rather than a namestring, and
*ICON-PATH* a list of pathnames.
From: Stormcoder
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <1146685631.305534.40770@v46g2000cwv.googlegroups.com>
This is good info. I appreciate it. The reason I didn't put the
asterisks in the symbol names was that they looked funny in the config
file. Asthetics might not be a good excuse but what can I say.  I'm
trying for an init file similar to emacs.
From: Kalle Olavi Niemitalo
Subject: Re: Loading a config file at run time
Date: 
Message-ID: <87zmhzuei7.fsf@Astalo.kon.iki.fi>
Bill Atkins <············@rpi.edu> writes:

> "Stormcoder" <·········@gmail.com> writes:
>> As I understand it, load takes place at read time, not run time. The
>> intent of the eval is so that load is executed at run time. Being a
>> novice, I could be wrong.
>
> You understand it incorrectly. :) LOAD is just a function; it is
> evaluated at execution-time.

And, if there were a Lisp whose LOAD operated at read time,
wrapping it in EVAL as in (eval (load "some.file")) would
probably still load the file at read time.  One would instead
have to do (eval '(load "some.file")).  Emacs Lisp sometimes
uses similar forms to disable the compile-time effects of its
require operator.

(The REQUIRE function of Common Lisp has no compile-time effects
specified for it.  If it had, then they would probably depend on
the form being at top level, and so one would be able to disable
them with (let () ...), which I think is somewhat cleaner than
(eval '...).)