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