From: ·······@ravenpack.com
Subject: Why not with-unique-syms (rather than with-gensyms)?
Date: 
Message-ID: <b75e806e-9815-4e57-8358-5ee42eabc62a@21g2000hsj.googlegroups.com>
When writing macros, one often uses something like with-gensyms for
lots of good reasons.  I mean something like what Paul Graham uses in
"On Lisp"

(defmacro with-gensyms (symbols &body body)
  "Binds a whole list of variables to gensyms."
  `(let ,(mapcar #'(lambda (symbol) `(,symbol (gensym)))
                 symbols)
     ,@body))

This works great and solves all the problems it is supposed to.  But
it leads to macro expansions that look like what follows (from the
with-redraw example also in "On Lisp")

(let ((#:g1000 objs))
  (multiple-value-bind (#:g1001 #:g1002 #:g1003 #:g1004) (bounds
#:g1000)
    (dolist (o #:g1000) (incf (obj-x o) dx) (incf (obj-y o) dy))
    (multiple-value-bind (xa ya xb yb) (bounds #:g1000)
      (redraw (min #:g1001 xa) (min #:g1002 ya)
              (min #:g1003 xb) (min #:g1004 yb)))))

While this is manageable, the gensym names are far from obvious and
can make debugging more difficult.  So why not do something like with-
unique-syms instead?

(defmacro with-unique-syms (symbols &body body)
  "Binds a whole list of variables to fresh, uninterned symbols"
  `(let ,(mapcar #'(lambda (symbol)
                     `(,symbol (make-symbol ,(string symbol))))
                 symbols)
     ,@body))

And then get a macro-expansion that looks like this:

(let ((#:gob objs))
  (multiple-value-bind (#:x0 #:y0 #:x1 #:y1) (bounds #:gob)
    (dolist (o #:gob) (incf (obj-x o) dx) (incf (obj-y o) dy))
    (multiple-value-bind (xa ya xb yb) (bounds #:gob)
      (redraw (min #:x0 xa) (min #:y0 ya)
              (min #:x1 xb) (min #:y1 yb)))))

The hyperspec even says (in 10.2.7 gensym):
"(The only difference between gensym and make-symbol is in how the new-
symbol's name is determined.)"

So I am pretty sure this would work, but since I've not seen it
suggested before, I wonder if there is a good reason to prefer the
(gensym) approach.

From: Pascal Costanza
Subject: Re: Why not with-unique-syms (rather than with-gensyms)?
Date: 
Message-ID: <5v8pftF1lkvokU1@mid.individual.net>
·······@ravenpack.com wrote:
> The hyperspec even says (in 10.2.7 gensym):
> "(The only difference between gensym and make-symbol is in how the new-
> symbol's name is determined.)"
> 
> So I am pretty sure this would work, but since I've not seen it
> suggested before, I wonder if there is a good reason to prefer the
> (gensym) approach.

copy-symbol is even more straightforward.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Peder O. Klingenberg
Subject: Re: Why not with-unique-syms (rather than with-gensyms)?
Date: 
Message-ID: <kstzlchgmv.fsf@beto.netfonds.no>
·······@ravenpack.com writes:

> (defmacro with-unique-syms (symbols &body body)
>   "Binds a whole list of variables to fresh, uninterned symbols"
>   `(let ,(mapcar #'(lambda (symbol)
>                      `(,symbol (make-symbol ,(string symbol))))
>                  symbols)
>      ,@body))

If you use the same variable name in multiple nestings of this, it
will be hard to tell one #:symbol from another while debugging.  Even
harder than with the gensym solution you presented first.

Fortunately, there is a better way.  Use the optional argument to
gensym:

(defmacro with-gensyms (symbols &body body)
  "Binds a whole list of variables to gensyms."
  `(let ,(mapcar #'(lambda (symbol) `(,symbol (gensym ,(string symbol))))
                 symbols)
     ,@body))


CL-USER> (with-gensyms (foo bar baz) (list foo bar baz))
(#:FOO19904 #:BAR19905 #:BAZ19906)

...Peder...
-- 
This must be Thursday.  I never could get the hang of Thursdays.
From: ·······@ravenpack.com
Subject: Re: Why not with-unique-syms (rather than with-gensyms)?
Date: 
Message-ID: <6f354f30-3460-42e9-99f5-6403372b88f2@l1g2000hsa.googlegroups.com>
On Jan 17, 11:48 am, ·····@news.klingenberg.no (Peder O. Klingenberg)
wrote:
> If you use the same variable name in multiple nestings of this, it
> will be hard to tell one #:symbol from another while debugging.  Even
> harder than with the gensym solution you presented first.
>
> Fortunately, there is a better way.  Use the optional argument to
> gensym:
>
> (defmacro with-gensyms (symbols &body body)
>   "Binds a whole list of variables to gensyms."
>   `(let ,(mapcar #'(lambda (symbol) `(,symbol (gensym ,(string symbol))))
>                  symbols)
>      ,@body))

Yes, nesting is a very legitimate concern for readability/debug-
ability.  I knew there was something obvious I wasn't considering.
Thanks.

-Jason
From: Pascal J. Bourguignon
Subject: Re: Why not with-unique-syms (rather than with-gensyms)?
Date: 
Message-ID: <7cd4s0ln3n.fsf@pbourguignon.anevia.com>
·······@ravenpack.com writes:

> When writing macros, one often uses something like with-gensyms for
> lots of good reasons.  I mean something like what Paul Graham uses in
> "On Lisp"
>
> (defmacro with-gensyms (symbols &body body)
>   "Binds a whole list of variables to gensyms."
>   `(let ,(mapcar #'(lambda (symbol) `(,symbol (gensym)))
>                  symbols)
>      ,@body))
>
> This works great and solves all the problems it is supposed to.  But
> it leads to macro expansions that look like what follows (from the
> with-redraw example also in "On Lisp")
>
> (let ((#:g1000 objs))
>   (multiple-value-bind (#:g1001 #:g1002 #:g1003 #:g1004) (bounds
> #:g1000)
>     (dolist (o #:g1000) (incf (obj-x o) dx) (incf (obj-y o) dy))
>     (multiple-value-bind (xa ya xb yb) (bounds #:g1000)
>       (redraw (min #:g1001 xa) (min #:g1002 ya)
>               (min #:g1003 xb) (min #:g1004 yb)))))
>
> While this is manageable, the gensym names are far from obvious and
> can make debugging more difficult.  So why not do something like with-
> unique-syms instead?
>
> (defmacro with-unique-syms (symbols &body body)
>   "Binds a whole list of variables to fresh, uninterned symbols"
>   `(let ,(mapcar #'(lambda (symbol)
>                      `(,symbol (make-symbol ,(string symbol))))
>                  symbols)
>      ,@body))
>
> And then get a macro-expansion that looks like this:
>
> (let ((#:gob objs))
>   (multiple-value-bind (#:x0 #:y0 #:x1 #:y1) (bounds #:gob)
>     (dolist (o #:gob) (incf (obj-x o) dx) (incf (obj-y o) dy))
>     (multiple-value-bind (xa ya xb yb) (bounds #:gob)
>       (redraw (min #:x0 xa) (min #:y0 ya)
>               (min #:x1 xb) (min #:y1 yb)))))
>
> The hyperspec even says (in 10.2.7 gensym):
> "(The only difference between gensym and make-symbol is in how the new-
> symbol's name is determined.)"
>
> So I am pretty sure this would work, but since I've not seen it
> suggested before, I wonder if there is a good reason to prefer the
> (gensym) approach.

Hi!

http://darcs.informatimago.com/darcs/public/lisp/common-lisp/utility.lisp has:

#-:with-debug-gensym
(DEFMACRO WITH-GENSYMS (SYMS &BODY BODY)
  "
DO:      Replaces given symbols with gensyms. Useful for creating macros.
NOTE:    This version by Paul Graham in On Lisp."
  `(LET ,(MAPCAR (LAMBDA (S) `(,S (GENSYM ,(string s)))) SYMS) ,@BODY))
;;                                        ^^^^^^^^^^^


There's also another version:

#+:with-debug-gensym
(defpackage "COM.INFORMATIMAGO.GENSYMS" (:USE))
#+:with-debug-gensym
(DEFMACRO WITH-GENSYMS (SYMS &BODY BODY)
  "
DO:      Replaces given symbols with gensyms. Useful for creating macros.
  `(LET ,(MAPCAR
          (LAMBDA (S) `(,S (INTERN (STRING (GENSYM ,(string s)))
                                   "COM.INFORMATIMAGO.GENSYMS"))) SYMS) ,@BODY))

which let you use these symbol more easily in a debugger.



AFAIK:

(let ((counter 0))
  (defun gensym (&optional (name "G"))
     (make-symbol (format nil name (incf counter)))))

so there should be no difference.


-- 
__Pascal Bourguignon__
From: lisp linux
Subject: Re: Why not with-unique-syms (rather than with-gensyms)?
Date: 
Message-ID: <ooGdnaAHsZzc0w3anZ2dnUVZ_gydnZ2d@comcast.com>
·······@ravenpack.com wrote:
> When writing macros, one often uses something like with-gensyms for
> lots of good reasons.  I mean something like what Paul Graham uses in
> ........
> This works great and solves all the problems it is supposed to.  But
> it leads to macro expansions that look like what follows (from the
> with-redraw example also in "On Lisp")
> .......(gensym) approach.
There were no responses to
http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/76ac84f0495b4e3a
but it may be useful to you
-Antony