Re: which one of these with-gensym implementations is better?



cmo <amalawi@xxxxxxxxx> wrote:
+---------------
| PCL: (defmacro with-gensyms ((&rest names) &body body)
| `(let ,(loop for n in names collect `(,n (gensym)))
| ,@body))
|
| GLPS: (defmacro with-gensyms (symbols body)
| (sublis (mapcar #'(lambda (sym)
| (cons sym (gensym (string sym))))
| symbols)
| body))
|
| the only difference that I noticed was the fact that you need to use
| comma before variables in PCL with-gens while you do not need to do
| that in the other implementation.
| any other differences, insights.
+---------------

Well, the second one has a bug, at least when being used in a Lisp2
[or LispN] such as Common Lisp -- the SUBLIS is not sensitive to
whether a symbol to be substituted in the body is in the function
or a value position, so the following happens:

> (macroexpand-1
'(with-gensyms (list)
(let ((list (list 1 2 :three)))
(list (length list) list))))

(LET ((#:LIST1591 (#:LIST1591 1 2 :three)))
(#:LIST1591 (LENGTH #:LIST1591) #:LIST1591))
T
>

Oops! That's certainly not going to fly! ;-}

Whereas the PCL one not only requires you to be explicit about
*which* instances of the symbol(s) should be substituted, it also
assumes you will put the BODY of the WITH-GENSYMS inside its own
backquote, e.g.:

> (macroexpand-1
'(with-gensyms (list)
`(let ((,list (list 1 2 :three))) ; Note the initial backquote!
(list (length ,list) ,list))))

(LET ((LIST (GENSYM)))
`(LET ((,LIST (LIST 1 2 :three)))
(LIST (LENGTH ,LIST) ,LIST)))
T
> (eval *)

(LET ((#:G1610 (LIST 1 2 :three)))
(LIST (LENGTH #:G1610) #:G1610))
> (eval *)

(3 (1 2 :THREE))
>

Capische?


-Rob

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

.