Hi again,
I know I'm missing something simple here, but I've tried a bunch of stuff
and it just doesn't work...
My application needs to read a list of constants at compile time from a
file. I came up with this macro:
(defmacro my-file-to-string-list (fname)
(let ((stringlist)
(tmpstr))
(with-open-file (infile fname :direction :input)
(loop
(setq tmpstr (read-line infile nil nil))
(unless tmpstr
(return))
(push tmpstr stringlist)
))
(setq stringlist (nreverse stringlist))
stringlist
))
When I call this using
(setq mystrings (my-file-to-string-list myfilename))
I get an error that the first line of the file is invalid as a function
(it's apparently considering the opening paren of the list as a function
call). I know there must be something simple here (if I change the defmacro
to defun it will work, but doesn't get evaluated at load time or compile
time), and I think I've solved this (or seen it solved) before, but I'm just
not seeing it this time...
help, please!
thanks!
bufie
In article <······················@attbi_s52>,
"bufie" <·····@spamneggs.com> wrote:
> Hi again,
>
> I know I'm missing something simple here, but I've tried a bunch of stuff
> and it just doesn't work...
>
> My application needs to read a list of constants at compile time from a
> file. I came up with this macro:
>
> (defmacro my-file-to-string-list (fname)
> (let ((stringlist)
> (tmpstr))
> (with-open-file (infile fname :direction :input)
> (loop
> (setq tmpstr (read-line infile nil nil))
> (unless tmpstr
> (return))
> (push tmpstr stringlist)
> ))
> (setq stringlist (nreverse stringlist))
> stringlist
> ))
>
> When I call this using
> (setq mystrings (my-file-to-string-list myfilename))
>
> I get an error that the first line of the file is invalid as a function
> (it's apparently considering the opening paren of the list as a function
> call). I know there must be something simple here (if I change the defmacro
> to defun it will work, but doesn't get evaluated at load time or compile
> time), and I think I've solved this (or seen it solved) before, but I'm just
> not seeing it this time...
Macros are expected to expand into *code*, not data. The code for a
literal list of strings is (quote ("string1" "string2" ...)), but you're
expanding into ("string1" "string2" ...). Your macro should end with:
',stringlist
And would you *please* stop putting close parens on lines by themselves?
It's not how we do things around here.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Hi Barry,
"Barry Margolin" <······@alum.mit.edu> wrote in message
·································@comcast.dca.giganews.com...
> In article <······················@attbi_s52>,
> "bufie" <·····@spamneggs.com> wrote:
>
> > (defmacro my-file-to-string-list (fname)
> > (let ((stringlist)
> > (tmpstr))
> > (with-open-file (infile fname :direction :input)
> > (loop
> > (setq tmpstr (read-line infile nil nil))
> > (unless tmpstr
> > (return))
> > (push tmpstr stringlist)
> > ))
> > (setq stringlist (nreverse stringlist))
> > stringlist))
[snip]
> Macros are expected to expand into *code*, not data. The code for a
> literal list of strings is (quote ("string1" "string2" ...)), but you're
> expanding into ("string1" "string2" ...). Your macro should end with:
>
> ',stringlist
I had tried this, but since I didn't have a backquote anywhere in the macro
it didn't work. However, I just added one at the beginning of the last line
so it now looks like this:
`',stringlist
and it all seems to work now. Thanks very much for your help!
> And would you *please* stop putting close parens on lines by themselves?
> It's not how we do things around here.
will do. Sorry about that!
Thanks again!
bufie
"bufie" <·····@spamneggs.com> wrote
> My application needs to read a list of constants at compile time from a
> file. I came up with this macro:
Someone else will most likely help you write the macro. I just
wondered if you wouldn't do better to COMPILE-FILE the file with the
list of constants?
(COMPILE-FILE fname :LOAD T)
Sorry to immediately follow up to my own post, but I just tried one more
thing that seems to work. If I change the call to
(setq mystrings (macroexpand '(my-file-to-string-list myfilename)))
the variable mystrings gets set to a list of strings corresponding to the
lines in the file. Is this the right approach to do this, or is there a
better way?
thanks for your help!
bufie
"bufie" <·····@spamneggs.com> wrote in message
···························@attbi_s52...
> Hi again,
>
> I know I'm missing something simple here, but I've tried a bunch of stuff
> and it just doesn't work...
>
> My application needs to read a list of constants at compile time from a
> file. I came up with this macro:
>
> (defmacro my-file-to-string-list (fname)
> (let ((stringlist)
> (tmpstr))
> (with-open-file (infile fname :direction :input)
> (loop
> (setq tmpstr (read-line infile nil nil))
> (unless tmpstr
> (return))
> (push tmpstr stringlist)
> ))
> (setq stringlist (nreverse stringlist))
> stringlist
> ))
>
> When I call this using
> (setq mystrings (my-file-to-string-list myfilename))
>
> I get an error that the first line of the file is invalid as a function
> (it's apparently considering the opening paren of the list as a function
> call). I know there must be something simple here (if I change the
defmacro
> to defun it will work, but doesn't get evaluated at load time or compile
> time), and I think I've solved this (or seen it solved) before, but I'm
just
> not seeing it this time...
>
> help, please!
>
> thanks!
>
> bufie
>
>
Ok, I was wrong... This solution doesn't expand at compile time after
all -- I thought it would, but it still looks for the file with the text
strings in it...
It seems there's got to be a way to do this so that the constants will be
defined in the compiled code...
thanks in advance for any help you can provide!
bufie
"bufie" <·····@spamneggs.com> wrote in message
··························@attbi_s54...
> Sorry to immediately follow up to my own post, but I just tried one more
> thing that seems to work. If I change the call to
>
> (setq mystrings (macroexpand '(my-file-to-string-list myfilename)))
>
> the variable mystrings gets set to a list of strings corresponding to the
> lines in the file. Is this the right approach to do this, or is there a
> better way?
>
> thanks for your help!
>
> bufie
>
> "bufie" <·····@spamneggs.com> wrote in message
> ···························@attbi_s52...
> > Hi again,
> >
> > I know I'm missing something simple here, but I've tried a bunch of
stuff
> > and it just doesn't work...
> >
> > My application needs to read a list of constants at compile time from a
> > file. I came up with this macro:
> >
> > (defmacro my-file-to-string-list (fname)
> > (let ((stringlist)
> > (tmpstr))
> > (with-open-file (infile fname :direction :input)
> > (loop
> > (setq tmpstr (read-line infile nil nil))
> > (unless tmpstr
> > (return))
> > (push tmpstr stringlist)
> > ))
> > (setq stringlist (nreverse stringlist))
> > stringlist
> > ))
> >
> > When I call this using
> > (setq mystrings (my-file-to-string-list myfilename))
> >
> > I get an error that the first line of the file is invalid as a function
> > (it's apparently considering the opening paren of the list as a function
> > call). I know there must be something simple here (if I change the
> defmacro
> > to defun it will work, but doesn't get evaluated at load time or compile
> > time), and I think I've solved this (or seen it solved) before, but I'm
> just
> > not seeing it this time...
> >
> > help, please!
> >
> > thanks!
> >
> > bufie
> >
> >
>
>
bufie wrote:
> My application needs to read a list of constants at compile time from
> a file. I came up with this macro:
There is no need for this to be a macro. You can just make a simple
defun to do this. As long as the SETQ is at the toplevel, it will
happen at compile time.
Jeff
In article <·······················@attbi_s03>,
"Jeff" <···@nospam.insightbb.com> wrote:
> bufie wrote:
>
> > My application needs to read a list of constants at compile time from
> > a file. I came up with this macro:
>
> There is no need for this to be a macro. You can just make a simple
> defun to do this. As long as the SETQ is at the toplevel, it will
> happen at compile time.
No it won't, it generate code to call the function at load time.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
bufie wrote:
[snip macro]
> I get an error that the first line of the file is invalid as a function
yes, because macros return code, which is then evaluated. you have the
macro return a list, and that list will be evaluated as if it were code.
for evaluation at compilation time, CL provides EVAL-WHEN.
--
Joost Kremers ············@yahoo.com
Selbst in die Unterwelt dringt durch Spalten Licht
EN:SiS(9)
bufie wrote:
> Hi again,
>
> I know I'm missing something simple here, but I've tried a bunch of stuff
> and it just doesn't work...
>
> My application needs to read a list of constants at compile time from a
> file.
I am not 100% sure if this will work, but here is what I came up with
(untested!):
(defvar *mystrings*)
(eval-when (:compile-toplevel)
(setq *mystrings*
(with-open-file (infile fname :direction :input)
(loop for tmpstr = (read-line infile nil nil)
while tmpstr
collect tmpstr))))
However, I think Peter Lewerin's suggestion is the better idea. If you
can manage to have the constants defined in that infile just be a Lisp
constant then you should be done:
(defconstant +mystrings+ (list "foo" "bar" "baz"))
Pascal
--
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
"bufie" <·····@spamneggs.com> writes:
>
> Hi again,
>
> I know I'm missing something simple here, but I've tried a bunch of stuff
> and it just doesn't work...
>
> My application needs to read a list of constants at compile time from a
> file. I came up with this macro:
This is not a job for a macro.
This is a job for EVAL-WHEN.
--
Thomas A. Russ, USC/Information Sciences Institute
"bufie" <·····@spamneggs.com> writes:
Not at all connected with your original problem, but you can
exploit the full power of LOOP to greatly simplify this part
of the code:
> (let ((stringlist)
> (tmpstr))
> (with-open-file (infile fname :direction :input)
> (loop
> (setq tmpstr (read-line infile nil nil))
> (unless tmpstr
> (return))
> (push tmpstr stringlist)
> ))
> (setq stringlist (nreverse stringlist))
> stringlist
> ))
It can be transformed into:
(with-open-file (infile fname :direction :input)
(loop for tmpstr = (read-line infile nil nil)
while tmpstr
collect tmpstr))
This moves the variable "tmpstr" into the loop itself
and dispenses with "stringlist" entirely, since it isn't
needed. The LOOP "collect" form efficiently adds elements
to the end of the list, and that is what is returned by
the form.
(I kept your variable names, but I would usually call
"tmpstr" "line" instead...)
--
Thomas A. Russ, USC/Information Sciences Institute