I would like to construct a form (to be written to a Lisp source file
and loaded later), that references a variable BAR which in turn may be a
symbol, a string or a number. In all cases, the value of BAR is the name
of some object. To account for the case where the variable evaluates to
a symbol, I need to include a quote to prevent evaluation when the form
is read at a later time, thus:
(let ((bar 'baz)) `(foo ',bar)) => (FOO 'BAZ)
Of course, when BAR evaulates to a string or number, the quote is
retained in the result:
(let ((bar "baz")) `(foo ',bar)) => (FOO '"baz")
(let ((bar 123)) `(foo ',bar)) => (FOO '123)
Since
(equal '"baz" "baz") => t
(equal '123 123) => t
this result is *correct*, but I suspect that there should be a simple
way to avoid quoted strings and numbers in such a construction.
Any suggestions (or comments on why the above is not good Lisp "style")
will be appreciated.
Best,
Lyle
Lyle Graham <····@biomedicale.univ-paris5.fr> wrote in message news:<················@biomedicale.univ-paris5.fr>...
> I would like to construct a form (to be written to a Lisp source file
> and loaded later), that references a variable BAR which in turn may be a
> symbol, a string or a number. In all cases, the value of BAR is the name
> of some object.
To clarify, the form you are writing to the file does not actually
refer to a BAR variable. Rather, the backquoted template which is used
to construct that from refers to a BAR variable. The substitution of
BAR's value occurs when you construct the form before you write it to
the file.
> To account for the case where the variable evaluates to
> a symbol, I need to include a quote to prevent evaluation when the form
> is read at a later time, thus:
No, reading and evaluation are different things. Reading does not lead
to evaluation (except for read-time evaluation requested by the #.
notation). But you will run into that problem when you later evaluate
the form you have read.
> (let ((bar 'baz)) `(foo ',bar)) => (FOO 'BAZ)
Try (read-from-string "(FOO BAZ)") for instance: no attempt is made to
evaluate BAZ or to call the function FOO. But of course if you EVAL
the object that has been read, then yes.
> Of course, when BAR evaulates to a string or number, the quote is
> retained in the result:
>
> (let ((bar "baz")) `(foo ',bar)) => (FOO '"baz")
It's okay to quote things which already evaluate to themselves. It's a
general way to suppress evaluation of anything and make it stand for
itself.
> (let ((bar 123)) `(foo ',bar)) => (FOO '123)
>
>
> Since
>
> (equal '"baz" "baz") => t
> (equal '123 123) => t
>
> this result is *correct*, but I suspect that there should be a simple
> way to avoid quoted strings and numbers in such a construction.
One quick and dirty hack would be: insert the quote only if the object
satisfies CONSP or SYMBOLP.
(let ((bar 123))
`(foo ,(if (or (consp bar) (symbolp bar))
`(quote ,bar)
bar)))
Are there any other things whose evaluation you have to worry about
beside symbols and lists?
> Any suggestions (or comments on why the above is not good Lisp "style")
> will be appreciated.
It's fine. It depends on whether, in the given situation, you care
more about programming convenience or storing the data in a pristine
format.
Thanks very much to all for the suggestions. I had previously used a
similar explicit check for SYMBOLP while adding the quote or not to a
FORMAT statement.
Kaz Kylheku wrote:
>
> One quick and dirty hack would be: insert the quote only if the object
> satisfies CONSP or SYMBOLP.
>
> (let ((bar 123))
> `(foo ,(if (or (consp bar) (symbolp bar))
> `(quote ,bar)
> bar)))
I suppose the following macro is generally useful:
(defmacro quote-only-symbol (val)
`(if (and (symbolp ,val) (not (keywordp ,val))) `',,val ,val))
Thus
(let ((bar 123))
`(foo ,(quote-only-symbol bar)))
>>Any suggestions (or comments on why the above is not good Lisp "style")
>>will be appreciated.
>
>
> It's fine. It depends on whether, in the given situation, you care
> more about programming convenience or storing the data in a pristine
> format.
Yes, in fact my concern was for a "pristine" data format, specifically
to avoid non-Lisp-savvy users from scratching their heads over '"foo"
and '123.
Lyle
Lyle Graham <····@biomedicale.univ-paris5.fr> wrote in message news:<················@biomedicale.univ-paris5.fr>...
> Thanks very much to all for the suggestions. I had previously used a
> similar explicit check for SYMBOLP while adding the quote or not to a
> FORMAT statement.
>
> Kaz Kylheku wrote:
>
> >
> > One quick and dirty hack would be: insert the quote only if the object
> > satisfies CONSP or SYMBOLP.
> >
> > (let ((bar 123))
> > `(foo ,(if (or (consp bar) (symbolp bar))
> > `(quote ,bar)
> > bar)))
>
> I suppose the following macro is generally useful:
>
> (defmacro quote-only-symbol (val)
> `(if (and (symbolp ,val) (not (keywordp ,val))) `',,val ,val))
Yes, but there is no reason why it has to be a macro, and if it had to
be one, I'd avoid the multiple evaluations of ,val by using a gensym.
;)
Also `',,val raises a bit of a red flag with me. You have more
backquoting and unquoting than necessary, all you need is:
(if ... ',val ,val)
Here is the function version:
;; all the macro taste, but less filling
(declaim (inline quote-only-symbol))
(defun quote-only-symbol (val)
(if (and (symbolp val)
(not (keywordp val)))
`(quote ,val)
val))
Lastly, you really do have to quote conses too, so it should be
quote-only-non-keyword-symbol-or-cons.
> Yes, in fact my concern was for a "pristine" data format, specifically
> to avoid non-Lisp-savvy users from scratching their heads over '"foo"
> and '123.
They will still scratch them over 'foo and '(+ a b). ;)
"Lyle Graham" <····@biomedicale.univ-paris5.fr> wrote in message
·····················@biomedicale.univ-paris5.fr...
> I would like to construct a form (to be written to a Lisp source file
> and loaded later), that references a variable BAR which in turn may be a
> symbol, a string or a number. In all cases, the value of BAR is the name
> of some object. To account for the case where the variable evaluates to
> a symbol, I need to include a quote to prevent evaluation when the form
> is read at a later time, thus:
>
> (let ((bar 'baz)) `(foo ',bar)) => (FOO 'BAZ)
>
>
> Of course, when BAR evaulates to a string or number, the quote is
> retained in the result:
>
> (let ((bar "baz")) `(foo ',bar)) => (FOO '"baz")
>
>
> (let ((bar 123)) `(foo ',bar)) => (FOO '123)
>
>
> Since
>
> (equal '"baz" "baz") => t
> (equal '123 123) => t
>
> this result is *correct*, but I suspect that there should be a simple
> way to avoid quoted strings and numbers in such a construction.
>
> Any suggestions (or comments on why the above is not good Lisp "style")
> will be appreciated.
>
> Best,
>
> Lyle
(let ((bar 'baz))
`(foo ,(if (and (symbolp bar) (not (keywordp bar)))
`',bar
bar)))
=>
(FOO 'BAZ)
(let ((bar 123))
`(foo ,(if (and (symbolp bar) (not (keywordp bar)))
`',bar
bar)))
=>
(FOO 123)
Regards,
jag
From: Tim Bradshaw
Subject: Re: Constructing forms with quoted atoms
Date:
Message-ID: <ey3r8ac70c8.fsf@cley.com>
* Lyle Graham wrote:
> this result is *correct*, but I suspect that there should be a simple
> way to avoid quoted strings and numbers in such a construction.
I think it's safe to say that only symbols and conses need to be
quoted (at least in any ANSI CL - CLtL1 CL was vaguer), so you can do
this by checking the type. However I don't think there's any need to
bother.
--tim