Subject: Re: Stupid newbie package question
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 19 Apr 2004 06:16:50 -0500
Newsgroups: comp.lang.lisp
Message-ID: <bcGdnWyb5rq_KB7dRVn-tA@speakeasy.net>
John Thingstad  <john.thingstad@chello.no> wrote:
+---------------
| '#+ test expression' runs expression if test is t used
| tha same way #ifdef is used in C
+---------------

Uh... This is somewhat misleading, especially since the OP is an
acknowledged newbie. First, there's no "running" implied at all --
this is purely a READ-time conditional, and applies to *any* READ,
not just ones which result in code, e.g., in CMUCL:

	> (read)
	(a b #+cmu c d e #-cmu f g)  ;I typed this

	(A B C D E G)
	> 

[I have used this occasionally to conditionalize data files built of
s-exprs.]

Second, when you say "if test is t", well, not really. That is, a feature
test is not an normal Lisp expression which is evaluated for a boolean
result using the ordinary rules for Lisp evaluation, as the term "test"
might ordinarily imply. Rather, a "test" here is a special form called
a "feature expression", which consists *only* of symbols (naming items
on the features list) and a few combining operators (AND, OR, & NOT).
A feature expression consisting of just a symbol "succeeds" or "fails"
depending on whether the feature named by the symbol is an element of
the list held by the variable *FEATURES* at the time the read occurs.
A complex feature expression succeeds or fails based on the obvious
AND/OR/NOT combination of the named feature(s):

	> (read)
	(a b #+cmu c1 #+allegro c2 d e #+(not (or cmu allegro)) f g)

	(A B C1 D E G)
	>

which could also be written as this:

	> (read)
	(a b #+cmu c1 #+allegro c2 d e #-(or cmu allegro) f g)

	(A B C1 D E G)
	>

The features list can be altered during the life of a given Lisp image,
e.g., by loading some library that modifies *FEATURES*, so some care must
be taken when using them.

	> #+foo "foo" #-foo "bar"

	"bar"
	> (push :foo *features*)
	(:FOO :ASDF :PCL-STRUCTURES :PORTABLE-COMMONLOOPS :PYTHON :PCL
	 :ELF :FREEBSD4 :FREEBSD :BSD :UNIX :LINKAGE-TABLE :GENCGC :MP
	 :PENTIUM :I486 :X86 :IEEE-FLOATING-POINT :ANSI-CL :COMMON-LISP
	 :COMMON :NEW-COMPILER :HASH-NEW :COMPLEX-FP-VOPS
	 :CONSERVATIVE-FLOAT-TYPE :RANDOM-MT19937 :RELATIVE-PACKAGE-NAMES
	 :CMU18E :CMU18 :CMU)
	> #+foo "foo" #-foo "not-foo"

	"foo"
	> 

Note that the feature test itself (though not the expressions which
follows it) is read with *PACKAGE* temporarily bound to KEYWORD, so
the elements of the features list should be keywords, too. [Yes, you
can hack around this, but it's not recommended for normal use.]

Finally, as with normal AND & OR special operators, the AND & OR
feature expression combiners succeed or fail (respectively) when
given the empty list, that is, #+(and) always succeeds and #+(or)
always fails. Conversely, #-(and) always fails and #-(or) always
succeeds.

You will see code that uses #+nil to "comment out" a complex s-expr.
There was a long thread here in c.l.lisp some time back which discussed
why this is a bad idea, and suggesting using #-(and) for this instead.
I like and use this latter form, since the normal connotations of + and -
are preserved: #+(and) always reads the following expression, and #-(and)
always ignores it.


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607