Subject: Re: Avoiding unintentional variable capture
From: (Rob Warnock)
Date: 1999/09/29
Newsgroups: comp.lang.lisp
Message-ID: <7ss1vq$>
Erik Naggum  <> wrote:
| * Erik Naggum
| | as I understand this, Scheme cannot generate symbols on the fly in code
| | in the first place, since the language is not defined in terms of sexprs...
| * Rob Warnock
| | [ example of generating symbols, but not on IN CODE elided ]
|   so how do you construct an expression that binds a value to a symbol thus
|   generated in its lexical scope?

In the usual way, either by explicitly using "eval", or by implicitly doing
so in the re-evaluation that occurs after a "defmacro" expansion, say:

	> (defmacro define-hyphenated-name (name1 name2 value) 
	   `(define ,(string->symbol (string-append (symbol->string name1)
						    (symbol->string name2)))
	> (define-hyphenated-name foo bar 43)
	> foo-bar

Or using explicit "eval":

	> (define (define-hyphenated-name name1 name2 value)  
	    (eval (list 'define
			   (string-append (symbol->string name1)
					  (symbol->string name2)))
	> (define-hyphenated-name 'gorp 'blat 67)
	> gorp-blat

But I'm not ducking your main point (as I understand it), which I take to
be that RxRS Scheme does not IN THE SPEC provide a low-level macro facility
such as "defmacro" which includes the needed re-evaluation by "eval" that
is needed to make any *use* of such generated sysmbols. It doesn't.

However... Given that RxRS *does* provide "eval", it is certainly possible
(and Jaffer's SLIB provides an example -- see the file "init.scm", which
contains a definition for "defmacro" & support hooks) to write an alternate
top-level REPL *in* RxRS Scheme that provides "defmacro" expansion (with
the attendant implicit "eval") for both hand-typed expressions and "load"ed
files, and thus makes gensyms usable.

Granted, you don't have access to those features until you've loaded the
init file that defines the stuff and overrides the standard REPL, but it
seems to work well enough in practice [given that most Schemes do support
*some* kind of init file]...


p.s. If I had run the above examples in a "pure" R5RS, I would have
had to add a second arg to "eval", specifying "(interaction-environment)".

p.p.s. Other have noted that the "gensym" implementation in RxRS Scheme
I showed does *not* produce uninterned symbols. That's correct, since
Scheme's "string->symbol" only produces interned symbols. So one's various
macros and other gensym users have to "cooperate", at least a *tiny* bit.
On the other hand, if all the symbols produced by "gensym" start with
something like |XyZzYx| or the like, avoiding symbol clash probably isn't
*that* difficult.  ;-}

Rob Warnock, 8L-846
Applied Networking
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		FAX: 650-933-0511
Mountain View, CA  94043	PP-ASEL-IA