Subject: Re: Any programmable way to ask whether a symbol has been proclaimed special?
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 12 May 2008 03:08:26 -0500
Newsgroups: comp.lang.lisp
Message-ID: <isKdndAS_6RnZ7rVnZ2dnUVZ_sHinZ2d@speakeasy.net>
Robert Maas <usenet2.3.CalRobert@SpamGourmet.Com> wrote:
+---------------
| Then suddenly I remembered DESCRIBE, which printed out among other things:
|   It is a special variable; no current value.
| OK, so I should have thought of that first. But there's no SPECIALP
| predicate or anything else I can find. How does DESCRIBE know that
| the symbol is special? How does the JIT compiler built into the
| REP loop know that it's special when it's deciding whether to do
| lexical or special bindings?
...
| This is in CMUCL, if it makes any difference. I'm hoping for some
| ANSI-CL function (predicate) rather than a CMUCL-specific function
| (predicate), but I'm curious in any case.
+---------------

I could give you a CMUCL-specific answer, involving macroexpanding
(DEFVAR *FOO*) [*without* setting a value] and then poking around
in the CMUCL sources and eventually finding that you might want to
use the dreaded infamous CMUCL "INFO" database that DESCRIBE uses
internally [see the source at "~cmucl-19c/src/code/describe.lisp"]:

    cmu> (info variable kind '*foo*)

    :GLOBAL
    NIL

    cmu> (defvar *foo*)

    *FOO*
    cmu> (info variable kind '*foo*)

    :SPECIAL
    T
    cmu> 

[Other possible answers for INFO VARIABLE KIND are :CONSTANT
(for DEFCONSTANT), :MACRO (for symbol macros), and :ALIEN (for
the CMUCL's "alien" FFI data), so you'd want to be prepared
for all of those, too. Similar things are available for INFO
FUNCTION KIND, but I don't think you really want to go there.]

But that's really a red herring, sorry to bring it up...  ;-}  ;-}

If you're trying to be portable, probably the best thing you can do
is send the output of DESCRIBE to a string stream and then use a
simple per-implementation pattern match to pull the info you need
out of it. That's likely to be more stable than any weird internal
interfaces [such as CMUCL's INFO], and *much* easier to add support
for new implementations:

    (defun globally-special-p (symbol)
      (let ((description (with-output-to-string (s) (describe symbol s))))
	#+cmu (search "It is a special variable" description)
	#+clisp (search "variable declared SPECIAL" description)
	;; Add more implementations here...
	#-(or cmu clisp)
	  (error "Not supported in ~A" (lisp-implementation-type))))

This group could probably flesh that out for a dozen more
implementations in only a handful of followup posts...  ;-}  ;-}


-Rob

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