Message from discussion
Avoiding unintentional variable capture
From: "Howard R. Stearns" <how...@elwood.com>
Subject: Re: Avoiding unintentional variable capture
Date: 1999/09/10
Message-ID: <37D95A13.572DC79B@elwood.com>#1/1
X-Deja-AN: 523502884
Content-Transfer-Encoding: 7bit
References: <37d6b784.46829757@judy> <slrn7tdigg.s9f.wtanksle@dolphin.openprojects.net> <m2btbdm3r7.fsf@sophia.axel.nom>
Content-Type: text/plain; charset=us-ascii
Organization: Elwood Corp. (http://www.elwood.com/eclipse-info)
X-NETCOM-Date: Fri Sep 10 2:20:53 PM CDT 1999
Mime-Version: 1.0
Newsgroups: comp.lang.lisp
Taking a naming cue from Harlequin in an attempt at consensus building,
Eclipse calls this WITH-UNIQUE-NAMES. (Note that
with-unqique-names/with-gensyms is a little different than William's
hygenic-let example.)
Anyway, if you find WITH-UNIQUE-NAMES useful (as I do every day) then
you will also find REBINDING useful, too. (REBINDING serves the same
purpose as what is called ONCE-ONLY in some implementations.) The doc
for both is at http://www.elwood.com/eclipse/rebinding.htm and
http://www.elwood.com/eclipse/unique.htm
Here's a definition for both. (I'm with Erik on the issue of having
macro-generated symbols use the names provided by the programmer. You
can disagree and use GENSYM if you like.)
A smile-and-a-handshake to anyone who can lucidly explain (no pun
intended) WHY the REBINDING code works, or conversely, convince me that
it doesn't.
(defmacro WITH-UNIQUE-NAMES (vars &body body)
`(let ,(loop for var in vars
collect `(,var ,(copy-symbol var)))
,@body))
(defmacro REBINDING (vars &body body) ;difficult code here!..
(loop for var in vars
for name = (copy-symbol var)
collect `(,name ,var) into renames
collect ``(,,var ,,name) into temps
finally (return `(let ,renames
(with-unique-names ,vars
`(let (,,@temps)
,,@body))))))
Johan Kullstam wrote:
>
> wtank...@dolphin.openprojects.net (William Tanksley) writes:
>
> > On Wed, 08 Sep 1999 20:10:23 GMT, Reini Urban wrote:
> > >Stupid subject line.
> >
> > Grin.
> >
> > >But reading the Tanksley-Joswig talk, Tanksley complaining about the
> > >semantic problem with macros, I thought why not writing a compiler which
> > >can automatically rename such captured vars in a new special form,
> > >defmacro-alike. something like DEFSAFEMACRO. "On Lisp" could be thrown
> > >away then :)
> >
> > No! Anaphor is a powerful thing, and any change to avoid its bad effects
> > would also destroy its good ones (and thus obsolete all macros).
> >
> > Lisp doesn't need to be changed to avoid accidental symbol capture. All
> > you have to do is define and use a very simple macro, let's call it
> > "hygenic-let", which uses 'let' and 'gensym' to create new variables which
> > will shadow the old ones.
> >
> > An example of its usage would be:
> >
> > (defmacro duh (x y z)
> > (hygenic-let ((i 1) (j 2))
> > (do-things i x y z)
> > j))
> >
> > Make sense? This has just declared i and j to be hygenic -- secretly,
> > it's replaced every use of i and j with a new gensym.
> >
> > 'On Lisp' defines this macro, IIRC, but I don't remember what it
> > called it.
>
> graham called it WITH-GENSYMS
>
> (defmacro with-gensyms (syms &body body)
> `(let ,(mapcar #'(lambda (s)
> `(,s (gensym)))
> syms)
> ,@body))
>
> here's an example of its use
>
> (defmacro allf (val &rest args)
> (with-gensyms (gval)
> `(let ((,gval ,val))
> (setf ,@(mapcan #'(lambda (a) (list a gval))
> args)))))
>
> i find WITH-GENSYMS to be highly useful.
>
> > >No really, a decent compiler should be able to do the static analysis of
> > >possible variable captures in special macros and rename/gensym them.
> > >(Letting dynamic creation of such DEFSAFEMACRO's aside.)
>
> nod. INLINE is supposed to do this (no comments about any particular
> implementations). this also barring the effect of SETF not
> escaping the scope of the function problem.
>
> --
> J o h a n K u l l s t a m
> [kulls...@ne.mediaone.net]
> Don't Fear the Penguin!