Subject: Re: Macros that build function names
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 09 Aug 2003 06:37:50 -0500
Newsgroups: comp.lang.lisp
Message-ID: <D6ycncbcCIWTQKmiXTWc-g@speakeasy.net>
Kent M Pitman  <pitman@world.std.com> wrote:
+---------------
| rpw3@rpw3.org (Rob Warnock) writes:
| > (defmacro deflex (var val &optional (doc nil docp))    
...
| >   (let* ((s0 (load-time-value (symbol-name '#:*storage-for-deflex-var-)))
| 
| Sigh. What's the advantage of this over "STORAGE-FOR-DEFLEX-VAR-" ??
|
| > 	     (s2 (load-time-value (symbol-name '#:*)))
| And "*" ????
+---------------

It's only a visual reminder that there really *is* a normal special
variable out there that you'd better not try to bind. That is, when
someone does a DESCRIBE [at least in CMUCL] on the resulting lexical var,
they see both the documentation string and the backing variable name:

    > (deflex foo 42 "The answer to Life, The Universe, and Everything")

    FOO
    > (describe 'foo)

    FOO is an internal symbol in the COMMON-LISP-USER package.
    It is a symbol macro with expansion: *STORAGE-FOR-DEFLEX-VAR-FOO*.
    Macro documentation:
      The answer to Life, The Universe, and Everything
    > 

The "*...*" in the expansion is a reminder (to me, at least) that FOO
is really still only a special under the hood. That's all.

+---------------
| You don't have to use a symbol for this, btw.  A property or hash table
| should suffice and is safer. 
+---------------

Yes, well, I suspect those other implementations also have the following
problem, too, that no matter how useful the illusion of "globals lexicals"
is for interactive work, they're still *not* really first-class variables.
For example, given the above, this works fine:

    > (setf foo 26) 

    26
    > foo

    26
    >

but not this:

    > (setf (symbol-value 'foo) 53)

    53
    > foo

    26
    >

Oops!

+---------------
| I usually just use a hash table or plist entry that contains a cons
| cell to store into the cdr of.  (The car can usually be the symbol
| name, just for self-doc of the cell.)
+---------------

But then the run-time access of the "lexical" involves a hash table
lookup or GET overhead -- neither one negligible. Whereas the "backing
variable" approach really *is* just a variable access [after macroexpansion].

Anyway, it's not a biggy. The reason I use them at all is just so I
can type short, non-*...*'d names [e.g., "x" and "i"] at the listener
and not worry about some function's internal LET bindings accidentally
getting converted from lexical to special! That is, this:

	> (deflex x 27)
	> (load "foo.lisp")

is a *lot* safer than this:

	> (defvar x 27)
	> (load "foo.lisp")

And it works well enough for that.


-Rob

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