From: Marc Wachowitz
Subject: Re: beginner question
Date: 
Message-ID: <6hqk8g$dho$2@trumpet.uni-mannheim.de>
Erik Naggum <······@naggum.no> wrote:
> [...] since the compiler will barf
> on references to undeclared symbols, you need to access them explicitly
> with (SYMBOL-VALUE 'SYMBOL) and (SETF (SYMBOL-VALUE 'SYMBOL)).  this is
> not pretty, and might even be seen as thwarting the semantics of the
> language. 

I think the following works in a conforming Common Lisp implementation:

(defmacro defglobal (name &optional init)
  ;; documentation string support omitted for brevity
  (let ((place (make-symbol (symbol-string name))))
    `(progn
       (define-symbol-macro ,name (symbol-value ',place))
       (setq ,name ,init))))

I didn't test this, since CMU-CL (at least the version which I have now)
unfortunately doesn't implement DEFINE-SYMBOL-MACRO.

I suggest uninterned symbols, named just like the intended lexical global
variable, to increase readability in macro expansion and debugging output.
Of course, different forms of storage are possible. Note that one needs
to do something more complicated if DEFGLOBAL forms are meant to work
reasonably well when they are reloaded, without reloading everything
depending on them, e.g. in compiled functions referencing the previously
created uninterned symbol. For example, one could store such uninterned
symbols in some hash table accessed via the argument to DEFGLOBAL (which
is probably an ordinary symbol with a proper package, though that's not
required), and reuse the previously created uninterned symbol whenever a
DEFGLOBAL is repeated for the same symbol. Of course, this hash table
would then be made to survive reloading its definition (using DEFVAR or
an explicit SYMBOL-VALUE for an interned symbol, checking pre-existence).
This hash table would only be used when DEFGLOBAL is evaluated; variable
access would still go directly to the uninterned symbol, which is known
at symbol-macro expansion time. One should also support an optional type
declaration form in DEFGLOBAL calls, which would then wrap a THE form
around the expansion of the symbol-macro (ordinary declaration for such
"global variables" aren't possible).

I guess that's as close as one can come in Common Lisp to a true lexical
global variable. It's not very elegant, but once the machinery is defined,
usage should be relatively simple and work without horrible surprises.

-- Marc Wachowitz <··@ipx2.rz.uni-mannheim.de>
From: Kent M Pitman
Subject: Re: beginner question
Date: 
Message-ID: <sfwogxrhswl.fsf@world.std.com>
··@ipx2.rz.uni-mannheim.de (Marc Wachowitz) writes:

> I think the following works in a conforming Common Lisp implementation:
> 
> (defmacro defglobal (name &optional init)
>   ;; documentation string support omitted for brevity
>   (let ((place (make-symbol (symbol-string name))))
>     `(progn
>        (define-symbol-macro ,name (symbol-value ',place))
>        (setq ,name ,init))))
> 
> I didn't test this, since CMU-CL (at least the version which I have now)
> unfortunately doesn't implement DEFINE-SYMBOL-MACRO.

I don't think it will work, but not for the reasons you probably think
you checked.  Code that is externalized into a file is allowed to "split"
a gensym.  (symbol-value '<gensym>) will therefore not necessarily access
the same gensym in all cases (particularly, if references occur in two 
different compiled files).

I think something like the following will work better:

 (defmacro defglobal (name &optional init)
   `(progn
      (define-symbol-macro ,name
         (cdr (load-time-value (global-value-cell ',name))))
      (setq ,name ,init)
      ',name)) ;return the name, not its value

 (defun global-value-cell (name)
   (or (get name 'global-value-cell)
       (setf (get name 'global-value-cell)
	     (cons name ;for self-documentation
	           nil))))

> I guess that's as close as one can come in Common Lisp to a true lexical
> global variable. It's not very elegant, but once the machinery is defined,
> usage should be relatively simple and work without horrible surprises.

FWIW, DEFINE-SYMBOL-MACRO was added to Common Lisp exactly for cross-language
compatibility because it's useful in defining global lexicals and also 
global constants [that can't be setq'd but can be bound], which occur in
other dialects of Lisp (particularly ISLISP, the ISO Lisp Standard).