Peter Seibel <peter@javamonkey.com> wrote:
+---------------
| Barry Margolin <barry.margolin@level3.com> writes:
| > I think some implementations of CONSTANTP only recognize literals, not
| > variables declared with DEFCONSTANT.
|
| Should such implementations be considered non-conformant (in this
| area), given that the definition of CONSTANTP includes:
|
|
| * Constant variables, such as keywords, symbols defined by Common Lisp
| as constant (such as nil, t, and pi), and symbols declared as
| ^^^^^^^^^^^^^^^^^^^
| constant by the user in the indicated environment using defconstant
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| are always considered constant forms and must be recognized as such
| by constantp.
+---------------
I don't know if this is the same as the problem you're having, but I
ran into a similar problem[1] with DEFCONSTANT+CONSTANTP with CMUCL
during which I discovered to my chagrin that it appears conforming
for an implementation to report that a symbol was CONSTANTP at compile
time (due to DEFCONSTANT) yet *not* make it's value accessible at
compile time. A careful reading of CLHS "Macro DEFCONSTANT" eventually
showed why:
If a defconstant form appears as a top level form, the compiler
must recognize that name names a constant variable.
So far so good, but then in the next sentence:
An implementation may choose to evaluate the value-form at
compile time, load time, or both.
Thus, an implementation is explicitly permitted to *not* evaluate the
value-form at compile time, and CMUCL doesn't -- though it *does* report
the symbol to be CONSTANTP (as required). So you end up with a "constant"
that can't be usefully constant-folded by a user macro at compile time.[2]
-Rob
[1] Using a draft new version of Tim Bradshaw's HTOUT, which worked fine
at his site but broke at mine.
[2] Consider a macro that wants to compute a result at compile time iff
all of its arguments are CONSTANTP, otherwise it will emit code to
be evaluated at run-time [or perhaps load-time]. Using the simple
test (EVERY #'CONSTANTP args) is not sufficient [at least not in an
implementation such as CMUCL]. Instead, you need a more complex test
to be safe:
(every (lambda (x) (and (constantp x)
(or (keywordp x) (not (symbolp x)))))
args)
Or if some of your DEFCONSTANTs are in (EVAL-WHEN (:COMPILE-TOPLEVEL)...)
forms *and* you really, really want to pick those up [even if you
can't get the DEFCONSTANTs that aren't in such forms] you might want
to go to the trouble of doing this:
(every (lambda (x) (and (constantp x)
(or (not (symbolp x)) (boundp x))))
args)
Just remember to wrap the propor pieces of the macro in the proper
EVAL-WHENs...
-----
Rob Warnock, PP-ASEL-IA <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607