Subject: Re: Another environment question
From: rpw3@rpw3.org (Rob Warnock)
Date: Tue, 09 Sep 2003 06:10:46 -0500
Newsgroups: comp.lang.lisp
Message-ID: <E3ydncWvpN2rKMCiXTWc-g@speakeasy.net>
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