Subject: Re: Determining lexically bound variables inside a macro
From: rpw3@rpw3.org (Rob Warnock)
Date: Thu, 05 Aug 2004 05:51:46 -0500
Newsgroups: comp.lang.lisp
Message-ID: <6fWdnQF6DtTfjI_cRVn-qw@speakeasy.net>
Aneil Mallavarapu <aneil.mallavarapu@gmail.com> wrote:
+---------------
| rpw3@rpw3.org (Rob Warnock) wrote:
| > Yes, I have my own personal DEFLEX macro, and yes, I use it a lot
| > when doing exploratory programming interactively at the REPL, but I
| > don't use it at *all* in actual source code I write. Besides a few
| > subtle bugs[3], it just doesn't seem to feel stylistically correct
| > for wide use in Common Lisp (at least not yet).
| 
| It's a shame that CL hasn't defined such a thing.  I agree with your
| comments.  However, I'm at the experimental stages of building an
| embedded language, which I don't anticipate will be much used by
| LISPers.  Also, I anticipate reading and writing these global-lexical
| symbols a LOT... so I'm willing to experiment.
...
| >     You need to do this with some sort of DEFLEX macro that
| >     automatically munges the underlying variable name so that such
| >     collisions don't happen [or are at least *very* unlikely].
| 
| Yes, I ended up doing something like the following:
| 
| (defmacro defglobalconst (s val)
|   (let ((hidden-sym     (make-hidden-symbol s)))
|   `(eval-when (:compile-toplevel :load-toplevel :execute)
|      (defconstant ,hidden-sym ,v)
|      (define-symbol-macro ,s ,hidden-sym))
| 
| (defun make-hidden-symbol (s)
|   (intern (mkstr (symbol-package s) ":" (symbol-name s))
|           "HIDDEN-SYMBOL"))
+---------------

Well, for what it's worth, here's my current version:

    (defmacro deflex (var val &optional (doc nil docp))    
      (let* ((prefix (load-time-value (symbol-name '#:*storage-for-deflex-)))
	     (name (symbol-name var))
	     (backing-var (intern (concatenate 'string prefix name "*"))))
	`(progn
	   (defparameter ,backing-var ,val ,@(when docp `(,doc)))
	   ,@(when docp
	      `((setf (documentation ',var 'variable) ,doc)))
	   (define-symbol-macro ,var ,backing-var))))	; Must be last!

Note that it uses DEFPARAMETER, since I was trying to copy the
top-level behavior of Scheme's DEFINE (that is, unlike DEFVAR, later
ones override earlier ones), and it also handles documentation strings.


-Rob

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