Kent M Pitman <pitman@nhplace.com> wrote:
+---------------
| Incidentally, ignore the advice about global lexicals. For better or
| worse, I'm pretty sure all you want is this:
|
| (define-symbol-macro foo (symbol-value 'foo))
|
| Don't forget to use explicit special bindings when you really mean to
| bind these globals, since otherwise you'll get a lexical foo when you
| bind foo.
+---------------
For this reason, and also to avoid unbound-variable mistakes, e.g.:
> (define-symbol-macro foo (symbol-value 'foo))
FOO
> foo
Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable FOO is unbound.
[Condition of type UNBOUND-VARIABLE]
...
I would suggest providing/using some binding macro for such shadowable
specials to make it clear what's going on, something like this [feel
free to suggest a shorter yet still perspicuous name]:
> (defmacro defvar/shadowable (var &optional value (doc nil docp))
`(progn
(setf (symbol-value ',var) ,value)
,@(when docp
(list `(setf (documentation ',var 'variable) ,doc)))
(define-symbol-macro ,var (symbol-value ',var))))
DEFVAR/SHADOWABLE
> (defvar/shadowable foo 13 "An example shadowable special")
FOO
> (defun foo ()
"A function which gives the global value of FOO."
foo)
FOO
> (let ((foo 27))
(list foo (incf foo) foo
(foo) (locally (declare (special foo)) (incf foo)) (foo)))
(27 28 28 13 14 14)
> foo
14
>
The "DEFVAR/..." part of the name will suggest that this variable
*is* still intended to be used as a special at least in some contexts
while the ".../SHADOWABLE" [or some shorter, less-awkward phrase?]
will reassure one that its binding is lexically shadowable.
-Rob
p.s. I happen to think that having documentation strings
"just work" is worth a little extra effort in one's macros:
> (describe 'foo)
FOO is an internal symbol in the COMMON-LISP-USER package.
It is a symbol macro with expansion: (SYMBOL-VALUE 'FOO).
Macro documentation:
An example shadowable special
Function: #<Interpreted Function FOO {48A64D41}>
Function arguments:
There are no arguments.
Function documentation:
A function which gives the global value of FOO.
Its defined argument types are:
NIL
Its result type is:
*
Its definition is:
(LAMBDA () (BLOCK FOO FOO))
>
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607