From: rock69
Subject: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <6d726bdb-ee1b-41a7-8c3e-29b58280f355@a1g2000hsb.googlegroups.com>
I was doing some experimenting with MACROLET, just to figure out how
it works a little better, but I can't get the following code to work.
It only prints "Hello World!" once instead of 10 times. There's no
specific goal for this code. I was just experimenting for learning
purposes only.

(macrolet ((with-ps-gensyms ((&rest names) &body body)
			    `(let ,(loop for n in names collect `(,n (gensym)))
			       ,@body))
	   (ntimes (n &rest body)
		   `(with-ps-gensyms (g h)
				     `(let ((,h ,,n))
					(do ((,g 0 (+ ,g 1)))
					    ((>= ,g ,h))
					    ,,@body)))))
	  (ntimes 10 (format t "Hello World!~%")))

From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <c41d06e3-4b51-46f4-830b-7a4b03b6625b@79g2000hsk.googlegroups.com>
Tinkering a little, I've just discovered that it expands correctly by
replacing ,,@body with ,',@body which seems logical of course :) yet
it still requires one more evaluation step. In other words, it works
only if I replace the invocation (ntimes 10 (format t "Hello World!~
%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
course a ridiculous thing to have to do, so I'm still pretty much
stuck, only a little closer maybe to the solution.

rock69 wrote:
> I was doing some experimenting with MACROLET, just to figure out how
> it works a little better, but I can't get the following code to work.
> It only prints "Hello World!" once instead of 10 times. There's no
> specific goal for this code. I was just experimenting for learning
> purposes only.
>
> (macrolet ((with-ps-gensyms ((&rest names) &body body)
> 			    `(let ,(loop for n in names collect `(,n (gensym)))
> 			       ,@body))
> 	   (ntimes (n &rest body)
> 		   `(with-ps-gensyms (g h)
> 				     `(let ((,h ,,n))
> 					(do ((,g 0 (+ ,g 1)))
> 					    ((>= ,g ,h))
> 					    ,,@body)))))
> 	  (ntimes 10 (format t "Hello World!~%")))
From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <6f53479e-daed-4778-adb9-015fdb96319d@k13g2000hse.googlegroups.com>
On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
> Tinkering a little, I've just discovered that it expands correctly by
> replacing ,,@body with ,',@body which seems logical of course :) yet
> it still requires one more evaluation step. In other words, it works
> only if I replace the invocation (ntimes 10 (format t "Hello World!~
> %")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> course a ridiculous thing to have to do, so I'm still pretty much
> stuck, only a little closer maybe to the solution.
>
> rock69 wrote:
> > I was doing some experimenting with MACROLET, just to figure out how
> > it works a little better, but I can't get the following code to work.
> > It only prints "Hello World!" once instead of 10 times. There's no
> > specific goal for this code. I was just experimenting for learning
> > purposes only.
>
> > (macrolet ((with-ps-gensyms ((&rest names) &body body)
> >                        `(let ,(loop for n in names collect `(,n (gensym)))
> >                           ,@body))
> >       (ntimes (n &rest body)
> >               `(with-ps-gensyms (g h)
> >                                 `(let ((,h ,,n))
> >                                    (do ((,g 0 (+ ,g 1)))
> >                                        ((>= ,g ,h))
> >                                        ,,@body)))))
> >      (ntimes 10 (format t "Hello World!~%")))
>
>

OK, I got it all wrong. It turns out I didn't need nested backquotes
in the first place. This works fine:

(defmacro ntimes (n &rest body)
                   `(with-ps-gensyms (g h)
                                     (let ((,h ,n))
                                        (do ((,g 0 (+ ,g 1)))
                                            ((>= ,g ,h))
                                            ,@body))))

Looks like I've got some more studying to do :)

Does anyone know where I can find some really extensive info on
backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
Lisp, but it still feels like something's missing. Mr. Pitman help,
please.
From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <e3b4f3fa-25d8-43cb-9a31-83e93e8a9fa5@j22g2000hsf.googlegroups.com>
On Aug 21, 4:12 pm, rock69 <···········@gmail.com> wrote:
> On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
>
>
>
> > Tinkering a little, I've just discovered that it expands correctly by
> > replacing ,,@body with ,',@body which seems logical of course :) yet
> > it still requires one more evaluation step. In other words, it works
> > only if I replace the invocation (ntimes 10 (format t "Hello World!~
> > %")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> > course a ridiculous thing to have to do, so I'm still pretty much
> > stuck, only a little closer maybe to the solution.
>
> > rock69 wrote:
> > > I was doing some experimenting with MACROLET, just to figure out how
> > > it works a little better, but I can't get the following code to work.
> > > It only prints "Hello World!" once instead of 10 times. There's no
> > > specific goal for this code. I was just experimenting for learning
> > > purposes only.
>
> > > (macrolet ((with-ps-gensyms ((&rest names) &body body)
> > >                        `(let ,(loop for n in names collect `(,n (gensym)))
> > >                           ,@body))
> > >       (ntimes (n &rest body)
> > >               `(with-ps-gensyms (g h)
> > >                                 `(let ((,h ,,n))
> > >                                    (do ((,g 0 (+ ,g 1)))
> > >                                        ((>= ,g ,h))
> > >                                        ,,@body)))))
> > >      (ntimes 10 (format t "Hello World!~%")))
>
> OK, I got it all wrong. It turns out I didn't need nested backquotes
> in the first place. This works fine:
>
> (defmacro ntimes (n &rest body)
>                    `(with-ps-gensyms (g h)
>                                      (let ((,h ,n))
>                                         (do ((,g 0 (+ ,g 1)))
>                                             ((>= ,g ,h))
>                                             ,@body))))
>
> Looks like I've got some more studying to do :)
>
> Does anyone know where I can find some really extensive info on
> backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
> Lisp, but it still feels like something's missing. Mr. Pitman help,
> please.

Oops, the correct code is the following, sorry ...

(macrolet ((with-ps-gensyms ((&rest names) &body body)
			    `(let ,(loop for n in names collect `(,n (gensym)))
			       ,@body))
	   (ntimes (n &rest body)
		   `(with-ps-gensyms (g h)
				     (let ((,h ,n))
				       (do ((,g 0 (+ ,g 1)))
					   ((>= ,g ,h))
					   ,@body)))))
	  (ntimes 10 (format t "Hello World!~%")))
From: Kenny
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <48ad7bcb$0$7324$607ed4bc@cv.net>
rock69 wrote:
> On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
> 
>>Tinkering a little, I've just discovered that it expands correctly by
>>replacing ,,@body with ,',@body which seems logical of course :) yet
>>it still requires one more evaluation step. In other words, it works
>>only if I replace the invocation (ntimes 10 (format t "Hello World!~
>>%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
>>course a ridiculous thing to have to do, so I'm still pretty much
>>stuck, only a little closer maybe to the solution.
>>
>>rock69 wrote:
>>
>>>I was doing some experimenting with MACROLET, just to figure out how
>>>it works a little better, but I can't get the following code to work.
>>>It only prints "Hello World!" once instead of 10 times. There's no
>>>specific goal for this code. I was just experimenting for learning
>>>purposes only.
>>
>>>(macrolet ((with-ps-gensyms ((&rest names) &body body)
>>>                       `(let ,(loop for n in names collect `(,n (gensym)))
>>>                          ,@body))
>>>      (ntimes (n &rest body)
>>>              `(with-ps-gensyms (g h)
>>>                                `(let ((,h ,,n))
>>>                                   (do ((,g 0 (+ ,g 1)))
>>>                                       ((>= ,g ,h))
>>>                                       ,,@body)))))
>>>     (ntimes 10 (format t "Hello World!~%")))
>>
>>
> 
> OK, I got it all wrong. It turns out I didn't need nested backquotes
> in the first place. This works fine:
> 
> (defmacro ntimes (n &rest body)
>                    `(with-ps-gensyms (g h)
>                                      (let ((,h ,n))
>                                         (do ((,g 0 (+ ,g 1)))
>                                             ((>= ,g ,h))
>                                             ,@body))))
> 
> Looks like I've got some more studying to do :)
> 
> Does anyone know where I can find some really extensive info on
> backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
> Lisp, but it still feels like something's missing. Mr. Pitman help,
> please.

Do what I do, just keep adding and removing quotes and ticks and commas 
and moving them around at the same time until it works. This is where 
the monkeys really earn their bananas. Sometimes I break stuff out into 
a second macro just to keep my sanity. When it gets depressing, just 
remember, you could be trying to use Scheme to do macros. When you are 
ready to kill yourself, use F#.

hth, kenny
From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <ceada49e-4117-48bb-9aac-2115ef904331@e39g2000hsf.googlegroups.com>
On Aug 21, 4:27 pm, Kenny <·········@gmail.com> wrote:
> rock69 wrote:
> > On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
>
> >>Tinkering a little, I've just discovered that it expands correctly by
> >>replacing ,,@body with ,',@body which seems logical of course :) yet
> >>it still requires one more evaluation step. In other words, it works
> >>only if I replace the invocation (ntimes 10 (format t "Hello World!~
> >>%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> >>course a ridiculous thing to have to do, so I'm still pretty much
> >>stuck, only a little closer maybe to the solution.
>
> >>rock69 wrote:
>
> >>>I was doing some experimenting with MACROLET, just to figure out how
> >>>it works a little better, but I can't get the following code to work.
> >>>It only prints "Hello World!" once instead of 10 times. There's no
> >>>specific goal for this code. I was just experimenting for learning
> >>>purposes only.
>
> >>>(macrolet ((with-ps-gensyms ((&rest names) &body body)
> >>>                       `(let ,(loop for n in names collect `(,n (gensym)))
> >>>                          ,@body))
> >>>      (ntimes (n &rest body)
> >>>              `(with-ps-gensyms (g h)
> >>>                                `(let ((,h ,,n))
> >>>                                   (do ((,g 0 (+ ,g 1)))
> >>>                                       ((>= ,g ,h))
> >>>                                       ,,@body)))))
> >>>     (ntimes 10 (format t "Hello World!~%")))
>
> > OK, I got it all wrong. It turns out I didn't need nested backquotes
> > in the first place. This works fine:
>
> > (defmacro ntimes (n &rest body)
> >                    `(with-ps-gensyms (g h)
> >                                      (let ((,h ,n))
> >                                         (do ((,g 0 (+ ,g 1)))
> >                                             ((>= ,g ,h))
> >                                             ,@body))))
>
> > Looks like I've got some more studying to do :)
>
> > Does anyone know where I can find some really extensive info on
> > backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
> > Lisp, but it still feels like something's missing. Mr. Pitman help,
> > please.
>
> Do what I do, just keep adding and removing quotes and ticks and commas
> and moving them around at the same time until it works. This is where
> the monkeys really earn their bananas. Sometimes I break stuff out into
> a second macro just to keep my sanity. When it gets depressing, just
> remember, you could be trying to use Scheme to do macros. When you are
> ready to kill yourself, use F#.
>
> hth, kenny

:) Yeah, I guess it really is just a matter of trial and error. Like
Graham says, it's like trying to figure out a complex integral by just
looking at it.

F# no way! LOL
From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <be4815aa-2719-4e59-ad47-b2decaf5dd7e@f63g2000hsf.googlegroups.com>
On Aug 21, 5:02 pm, rock69 <···········@gmail.com> wrote:
> On Aug 21, 4:27 pm, Kenny <·········@gmail.com> wrote:
>
>
>
> > rock69 wrote:
> > > On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
>
> > >>Tinkering a little, I've just discovered that it expands correctly by
> > >>replacing ,,@body with ,',@body which seems logical of course :) yet
> > >>it still requires one more evaluation step. In other words, it works
> > >>only if I replace the invocation (ntimes 10 (format t "Hello World!~
> > >>%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> > >>course a ridiculous thing to have to do, so I'm still pretty much
> > >>stuck, only a little closer maybe to the solution.
>
> > >>rock69 wrote:
>
> > >>>I was doing some experimenting with MACROLET, just to figure out how
> > >>>it works a little better, but I can't get the following code to work.
> > >>>It only prints "Hello World!" once instead of 10 times. There's no
> > >>>specific goal for this code. I was just experimenting for learning
> > >>>purposes only.
>
> > >>>(macrolet ((with-ps-gensyms ((&rest names) &body body)
> > >>>                       `(let ,(loop for n in names collect `(,n (gensym)))
> > >>>                          ,@body))
> > >>>      (ntimes (n &rest body)
> > >>>              `(with-ps-gensyms (g h)
> > >>>                                `(let ((,h ,,n))
> > >>>                                   (do ((,g 0 (+ ,g 1)))
> > >>>                                       ((>= ,g ,h))
> > >>>                                       ,,@body)))))
> > >>>     (ntimes 10 (format t "Hello World!~%")))
>
> > > OK, I got it all wrong. It turns out I didn't need nested backquotes
> > > in the first place. This works fine:
>
> > > (defmacro ntimes (n &rest body)
> > >                    `(with-ps-gensyms (g h)
> > >                                      (let ((,h ,n))
> > >                                         (do ((,g 0 (+ ,g 1)))
> > >                                             ((>= ,g ,h))
> > >                                             ,@body))))
>
> > > Looks like I've got some more studying to do :)
>
> > > Does anyone know where I can find some really extensive info on
> > > backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
> > > Lisp, but it still feels like something's missing. Mr. Pitman help,
> > > please.
>
> > Do what I do, just keep adding and removing quotes and ticks and commas
> > and moving them around at the same time until it works. This is where
> > the monkeys really earn their bananas. Sometimes I break stuff out into
> > a second macro just to keep my sanity. When it gets depressing, just
> > remember, you could be trying to use Scheme to do macros. When you are
> > ready to kill yourself, use F#.
>
> > hth, kenny
>
> :) Yeah, I guess it really is just a matter of trial and error. Like
> Graham says, it's like trying to figure out a complex integral by just
> looking at it.
>
> F# no way! LOL

Now this REALLY puzzles me. Going back to the previous version and
feeding it to SBCL this is what I get:

> (macrolet ((with-ps-gensyms ((&rest names) &body body)
    `(let ,(loop for n in names collect `(,n (gensym)))
       ,@body))
   (ntimes (n &rest body)
   `(with-ps-gensyms (g h)
     `(let ((,h ,',n))
       (do ((,g 0 (+ ,g 1)))
   ((>= ,g ,h))
   ,',@body)))))
  (ntimes 10 (format t "Hello World!~%")))

OUTPUT:

(LET ((#:G605 10))
  (DO ((#:G604 0 (+ #:G604 1)))
      ((>= #:G604 #:G605))
    (FORMAT T "Hello World!~%")))

Like I said, it doesn't get evaluated, but the expansion appears to be
correct. Why doesn't it continue and evaluate it instead of stopping
at this point???
From: Thomas A. Russ
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <ymiej4i2toe.fsf@blackcat.isi.edu>
rock69 <···········@gmail.com> writes:

> Now this REALLY puzzles me. Going back to the previous version and
> feeding it to SBCL this is what I get:
> 
> > (macrolet ((with-ps-gensyms ((&rest names) &body body)
>     `(let ,(loop for n in names collect `(,n (gensym)))
>        ,@body))
>    (ntimes (n &rest body)
>    `(with-ps-gensyms (g h)
>      `(let ((,h ,',n))
>        (do ((,g 0 (+ ,g 1)))

     ^ ^ 

Um, you have two levels of (back)quoting going on.  That is what is
stopping the evaluation.  You want to drop the backquote in front of the
WITH-PS-GENSYMS invocation.  You want that macro to be expanded as an
aid to the generation of the macro-expansion of NTIMES.  You don't want
it to be part of that macroexpansion.

What I'm not sure of (and am too lazy to check the Hyperspect to find
out) is whether MACROLET works like FLET or LABELS as far as scope is
concerned.  You might need to use nested MACROLET forms if you can't use
the first macro definition while doing the expansion of the second.

>    ((>= ,g ,h))
>    ,',@body)))))
>   (ntimes 10 (format t "Hello World!~%")))

> OUTPUT:
> 
> (LET ((#:G605 10))
>   (DO ((#:G604 0 (+ #:G604 1)))
>       ((>= #:G604 #:G605))
>     (FORMAT T "Hello World!~%")))
> 
> Like I said, it doesn't get evaluated, but the expansion appears to be
> correct. Why doesn't it continue and evaluate it instead of stopping
> at this point???

Well, when debugging things like this, it is often useful to make these
be top-level macro definitions and then use MACROEXPAND and
MACROEXPAND-1 on them.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal J. Bourguignon
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <87ljyqcigb.fsf@hubble.informatimago.com>
···@sevak.isi.edu (Thomas A. Russ) writes:
> What I'm not sure of (and am too lazy to check the Hyperspect to find
> out) is whether MACROLET works like FLET or LABELS as far as scope is
> concerned.  You might need to use nested MACROLET forms if you can't use
> the first macro definition while doing the expansion of the second.

MARCROLET works like FLET, but it doesn't matter, as long as the macro
calls are quoted or backquoted, since that means they will be used
only when the body of the macrolet is  expanded, that is once all the
macros of the macrolet are defined.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

ADVISORY: There is an extremely small but nonzero chance that,
through a process known as "tunneling," this product may
spontaneously disappear from its present location and reappear at
any random place in the universe, including your neighbor's
domicile. The manufacturer will not be responsible for any damages
or inconveniences that may result.
From: viper-2
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <010820bc-4ee5-4733-9c5d-1183271a5178@v1g2000pra.googlegroups.com>
On Aug 21, 2:48 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> ····@sevak.isi.edu (Thomas A. Russ) writes:
>

> MARCROLET works like FLET, but it doesn't matter, as long as the macro
> calls are quoted or backquoted, since that means they will be used
> only when the body of the macrolet is  expanded, that is once all the
> macros of the macrolet are defined.

BTW Pascal, you forgot the "t" in "Software" in the title of your home
page:

"Pascal Bourguignon's Sofware"

at http://www.informatimago.com/


I'd love to spend some time discussing nested backquotes and macros
once I've finished this law project! I have played around with the
quotes, ticks, and commas too, getting different results, and just for
fun; but  there is a systematic approach that I know only comes from
practice. Later,

--agt
From: Pascal J. Bourguignon
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <87hc9ddi9o.fsf@hubble.informatimago.com>
viper-2 <········@mail.infochan.com> writes:

> On Aug 21, 2:48 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> ····@sevak.isi.edu (Thomas A. Russ) writes:
>>
>
>> MACROLET works like FLET, but it doesn't matter, as long as the macro
>> calls are quoted or backquoted, since that means they will be used
>> only when the body of the macrolet is  expanded, that is once all the
>> macros of the macrolet are defined.
>
> BTW Pascal, you forgot the "t" in "Software" in the title of your home
> page:
>
> "Pascal Bourguignon's Sofware"
>
> at http://www.informatimago.com/

Thanks.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
I need a new toy.
Tail of black dog keeps good time.
Pounce! Good dog! Good dog!
From: Thomas A. Russ
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <ymiabf62e8i.fsf@blackcat.isi.edu>
···@informatimago.com (Pascal J. Bourguignon) writes:

> ···@sevak.isi.edu (Thomas A. Russ) writes:
> > What I'm not sure of (and am too lazy to check the Hyperspect to find
> > out) is whether MACROLET works like FLET or LABELS as far as scope is
> > concerned.  You might need to use nested MACROLET forms if you can't use
> > the first macro definition while doing the expansion of the second.
> 
> MARCROLET works like FLET, but it doesn't matter, as long as the macro
> calls are quoted or backquoted, since that means they will be used
> only when the body of the macrolet is  expanded, that is once all the
> macros of the macrolet are defined.

Correct.

But the fix to the OP's problem was to remove the backquote from the
call to WITH-PS-GENSYMS so that it expands to form part of the expansion
function for NTIMES.  So he would therefore need to nest the MACROLET
forms so that that macro is available in the definition of NTIMES.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Geoffrey Summerhayes
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <48c318d3-8157-4bda-a890-8d73a1584af8@26g2000hsk.googlegroups.com>
On Aug 21, 11:25 am, rock69 <···········@gmail.com> wrote:
> On Aug 21, 5:02 pm, rock69 <···········@gmail.com> wrote:
>
>
>
>
>
> > On Aug 21, 4:27 pm, Kenny <·········@gmail.com> wrote:
>
> > > rock69 wrote:
> > > > On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
>
> > > >>Tinkering a little, I've just discovered that it expands correctly by
> > > >>replacing ,,@body with ,',@body which seems logical of course :) yet
> > > >>it still requires one more evaluation step. In other words, it works
> > > >>only if I replace the invocation (ntimes 10 (format t "Hello World!~
> > > >>%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> > > >>course a ridiculous thing to have to do, so I'm still pretty much
> > > >>stuck, only a little closer maybe to the solution.
>
> > > >>rock69 wrote:
>
> > > >>>I was doing some experimenting with MACROLET, just to figure out how
> > > >>>it works a little better, but I can't get the following code to work.
> > > >>>It only prints "Hello World!" once instead of 10 times. There's no
> > > >>>specific goal for this code. I was just experimenting for learning
> > > >>>purposes only.
>
> > > >>>(macrolet ((with-ps-gensyms ((&rest names) &body body)
> > > >>>                       `(let ,(loop for n in names collect `(,n (gensym)))
> > > >>>                          ,@body))
> > > >>>      (ntimes (n &rest body)
> > > >>>              `(with-ps-gensyms (g h)
> > > >>>                                `(let ((,h ,,n))
> > > >>>                                   (do ((,g 0 (+ ,g 1)))
> > > >>>                                       ((>= ,g ,h))
> > > >>>                                       ,,@body)))))
> > > >>>     (ntimes 10 (format t "Hello World!~%")))
>
> > > > OK, I got it all wrong. It turns out I didn't need nested backquotes
> > > > in the first place. This works fine:
>
> > > > (defmacro ntimes (n &rest body)
> > > >                    `(with-ps-gensyms (g h)
> > > >                                      (let ((,h ,n))
> > > >                                         (do ((,g 0 (+ ,g 1)))
> > > >                                             ((>= ,g ,h))
> > > >                                             ,@body))))
>
> > > > Looks like I've got some more studying to do :)
>
> > > > Does anyone know where I can find some really extensive info on
> > > > backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
> > > > Lisp, but it still feels like something's missing. Mr. Pitman help,
> > > > please.
>
> > > Do what I do, just keep adding and removing quotes and ticks and commas
> > > and moving them around at the same time until it works. This is where
> > > the monkeys really earn their bananas. Sometimes I break stuff out into
> > > a second macro just to keep my sanity. When it gets depressing, just
> > > remember, you could be trying to use Scheme to do macros. When you are
> > > ready to kill yourself, use F#.
>
> > > hth, kenny
>
> > :) Yeah, I guess it really is just a matter of trial and error. Like
> > Graham says, it's like trying to figure out a complex integral by just
> > looking at it.
>
> > F# no way! LOL
>
> Now this REALLY puzzles me. Going back to the previous version and
> feeding it to SBCL this is what I get:
>
> > (macrolet ((with-ps-gensyms ((&rest names) &body body)
>
>     `(let ,(loop for n in names collect `(,n (gensym)))
>        ,@body))
>    (ntimes (n &rest body)
>    `(with-ps-gensyms (g h)
>      `(let ((,h ,',n))
>        (do ((,g 0 (+ ,g 1)))
>    ((>= ,g ,h))
>    ,',@body)))))
>   (ntimes 10 (format t "Hello World!~%")))
>
> OUTPUT:
>
> (LET ((#:G605 10))
>   (DO ((#:G604 0 (+ #:G604 1)))
>       ((>= #:G604 #:G605))
>     (FORMAT T "Hello World!~%")))
>
> Like I said, it doesn't get evaluated, but the expansion appears to be
> correct. Why doesn't it continue and evaluate it instead of stopping
> at this point???- Hide quoted text -

Actually what came out was evaluated, it's just that what came
out was quoted.

(macrolet ((with-ps-gensyms ((&rest names) &body body)
             `(let ,(loop for n in names collect `(,n (gensym)))
                ,@body))
           (ntimes (n &rest body)
             `(with-ps-gensyms (g h)
                              (let ((h ,n))
                                 (do ((g 0 (+ g 1)))
                                     ((>= g h))
                                    ,@body)))))
  (ntimes 10 (format t "Hello World!~%")))

----
Geoff
From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <156cca29-1918-419f-ae64-d319fcee54b6@d1g2000hsg.googlegroups.com>
On Aug 21, 7:07 pm, Geoffrey Summerhayes <·······@gmail.com> wrote:
> On Aug 21, 11:25 am, rock69 <···········@gmail.com> wrote:
>
>
>
> > On Aug 21, 5:02 pm, rock69 <···········@gmail.com> wrote:
>
> > > On Aug 21, 4:27 pm, Kenny <·········@gmail.com> wrote:
>
> > > > rock69 wrote:
> > > > > On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
>
> > > > >>Tinkering a little, I've just discovered that it expands correctly by
> > > > >>replacing ,,@body with ,',@body which seems logical of course :) yet
> > > > >>it still requires one more evaluation step. In other words, it works
> > > > >>only if I replace the invocation (ntimes 10 (format t "Hello World!~
> > > > >>%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> > > > >>course a ridiculous thing to have to do, so I'm still pretty much
> > > > >>stuck, only a little closer maybe to the solution.
>
> > > > >>rock69 wrote:
>
> > > > >>>I was doing some experimenting with MACROLET, just to figure out how
> > > > >>>it works a little better, but I can't get the following code to work.
> > > > >>>It only prints "Hello World!" once instead of 10 times. There's no
> > > > >>>specific goal for this code. I was just experimenting for learning
> > > > >>>purposes only.
>
> > > > >>>(macrolet ((with-ps-gensyms ((&rest names) &body body)
> > > > >>>                       `(let ,(loop for n in names collect `(,n (gensym)))
> > > > >>>                          ,@body))
> > > > >>>      (ntimes (n &rest body)
> > > > >>>              `(with-ps-gensyms (g h)
> > > > >>>                                `(let ((,h ,,n))
> > > > >>>                                   (do ((,g 0 (+ ,g 1)))
> > > > >>>                                       ((>= ,g ,h))
> > > > >>>                                       ,,@body)))))
> > > > >>>     (ntimes 10 (format t "Hello World!~%")))
>
> > > > > OK, I got it all wrong. It turns out I didn't need nested backquotes
> > > > > in the first place. This works fine:
>
> > > > > (defmacro ntimes (n &rest body)
> > > > >                    `(with-ps-gensyms (g h)
> > > > >                                      (let ((,h ,n))
> > > > >                                         (do ((,g 0 (+ ,g 1)))
> > > > >                                             ((>= ,g ,h))
> > > > >                                             ,@body))))
>
> > > > > Looks like I've got some more studying to do :)
>
> > > > > Does anyone know where I can find some really extensive info on
> > > > > backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
> > > > > Lisp, but it still feels like something's missing. Mr. Pitman help,
> > > > > please.
>
> > > > Do what I do, just keep adding and removing quotes and ticks and commas
> > > > and moving them around at the same time until it works. This is where
> > > > the monkeys really earn their bananas. Sometimes I break stuff out into
> > > > a second macro just to keep my sanity. When it gets depressing, just
> > > > remember, you could be trying to use Scheme to do macros. When you are
> > > > ready to kill yourself, use F#.
>
> > > > hth, kenny
>
> > > :) Yeah, I guess it really is just a matter of trial and error. Like
> > > Graham says, it's like trying to figure out a complex integral by just
> > > looking at it.
>
> > > F# no way! LOL
>
> > Now this REALLY puzzles me. Going back to the previous version and
> > feeding it to SBCL this is what I get:
>
> > > (macrolet ((with-ps-gensyms ((&rest names) &body body)
>
> >     `(let ,(loop for n in names collect `(,n (gensym)))
> >        ,@body))
> >    (ntimes (n &rest body)
> >    `(with-ps-gensyms (g h)
> >      `(let ((,h ,',n))
> >        (do ((,g 0 (+ ,g 1)))
> >    ((>= ,g ,h))
> >    ,',@body)))))
> >   (ntimes 10 (format t "Hello World!~%")))
>
> > OUTPUT:
>
> > (LET ((#:G605 10))
> >   (DO ((#:G604 0 (+ #:G604 1)))
> >       ((>= #:G604 #:G605))
> >     (FORMAT T "Hello World!~%")))
>
> > Like I said, it doesn't get evaluated, but the expansion appears to be
> > correct. Why doesn't it continue and evaluate it instead of stopping
> > at this point???- Hide quoted text -
>
> Actually what came out was evaluated, it's just that what came
> out was quoted.
>
> (macrolet ((with-ps-gensyms ((&rest names) &body body)
>              `(let ,(loop for n in names collect `(,n (gensym)))
>                 ,@body))
>            (ntimes (n &rest body)
>              `(with-ps-gensyms (g h)
>                               (let ((h ,n))
>                                  (do ((g 0 (+ g 1)))
>                                      ((>= g h))
>                                     ,@body)))))
>   (ntimes 10 (format t "Hello World!~%")))
>
> ----
> Geoff

OK Geoff, thanks. I see what you mean.
From: Kaz Kylheku
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <20080821221637.818@kkylheku.gmail.com>
On 2008-08-21, rock69 <···········@gmail.com> wrote:
> On Aug 21, 5:02�pm, rock69 <···········@gmail.com> wrote:
>> On Aug 21, 4:27�pm, Kenny <·········@gmail.com> wrote:
>>
>>
>>
>> > rock69 wrote:
>> > > On Aug 21, 3:58 pm, rock69 <···········@gmail.com> wrote:
>>
>> > >>Tinkering a little, I've just discovered that it expands correctly by
>> > >>replacing ,,@body with ,',@body which seems logical of course :) yet
>> > >>it still requires one more evaluation step. In other words, it works
>> > >>only if I replace the invocation (ntimes 10 (format t "Hello World!~
>> > >>%")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
>> > >>course a ridiculous thing to have to do, so I'm still pretty much
>> > >>stuck, only a little closer maybe to the solution.
>>
>> > >>rock69 wrote:
>>
>> > >>>I was doing some experimenting with MACROLET, just to figure out how
>> > >>>it works a little better, but I can't get the following code to work.
>> > >>>It only prints "Hello World!" once instead of 10 times. There's no
>> > >>>specific goal for this code. I was just experimenting for learning
>> > >>>purposes only.
>>
>> > >>>(macrolet ((with-ps-gensyms ((&rest names) &body body)
>> > >>> � � � � � � � � � � � `(let ,(loop for n in names collect `(,n (gensym)))
>> > >>> � � � � � � � � � � � � �,@body))
>> > >>> � � �(ntimes (n &rest body)
>> > >>> � � � � � � �`(with-ps-gensyms (g h)
>> > >>> � � � � � � � � � � � � � � � �`(let ((,h ,,n))
>> > >>> � � � � � � � � � � � � � � � � � (do ((,g 0 (+ ,g 1)))
>> > >>> � � � � � � � � � � � � � � � � � � � ((>= ,g ,h))
>> > >>> � � � � � � � � � � � � � � � � � � � ,,@body)))))
>> > >>> � � (ntimes 10 (format t "Hello World!~%")))
>>
>> > > OK, I got it all wrong. It turns out I didn't need nested backquotes
>> > > in the first place. This works fine:
>>
>> > > (defmacro ntimes (n &rest body)
>> > > � � � � � � � � � �`(with-ps-gensyms (g h)
>> > > � � � � � � � � � � � � � � � � � � �(let ((,h ,n))
>> > > � � � � � � � � � � � � � � � � � � � � (do ((,g 0 (+ ,g 1)))
>> > > � � � � � � � � � � � � � � � � � � � � � � ((>= ,g ,h))
>> > > � � � � � � � � � � � � � � � � � � � � � � ,@body))))
>>
>> > > Looks like I've got some more studying to do :)
>>
>> > > Does anyone know where I can find some really extensive info on
>> > > backquote syntax? I've seen the HyperSpec, On Lisp, and ANSI Common
>> > > Lisp, but it still feels like something's missing. Mr. Pitman help,
>> > > please.
>>
>> > Do what I do, just keep adding and removing quotes and ticks and commas
>> > and moving them around at the same time until it works. This is where
>> > the monkeys really earn their bananas. Sometimes I break stuff out into
>> > a second macro just to keep my sanity. When it gets depressing, just
>> > remember, you could be trying to use Scheme to do macros. When you are
>> > ready to kill yourself, use F#.
>>
>> > hth, kenny
>>
>> :) Yeah, I guess it really is just a matter of trial and error. Like
>> Graham says, it's like trying to figure out a complex integral by just
>> looking at it.
>>
>> F# no way! LOL
>
> Now this REALLY puzzles me. Going back to the previous version and
> feeding it to SBCL this is what I get:
>
>> (macrolet ((with-ps-gensyms ((&rest names) &body body)
>     `(let ,(loop for n in names collect `(,n (gensym)))
>        ,@body))
>    (ntimes (n &rest body)
>    `(with-ps-gensyms (g h)
>      `(let ((,h ,',n))
>        (do ((,g 0 (+ ,g 1)))
>    ((>= ,g ,h))
>    ,',@body)))))
>   (ntimes 10 (format t "Hello World!~%")))
>
> OUTPUT:
>
> (LET ((#:G605 10))
>   (DO ((#:G604 0 (+ #:G604 1)))
>       ((>= #:G604 #:G605))
>     (FORMAT T "Hello World!~%")))
>
> Like I said, it doesn't get evaluated, but the expansion appears to be
> correct. Why doesn't it continue and evaluate it instead of stopping
> at this point???

Because it has already done the required number of evaluation rounds.

Your macro produced the code (WITH-PS-GENSYMS (G H) `(LET ((,H ,10)) ...)).

This expression was substituted in place of the macro. 

And this expression's action is to construct the list (LET ((#:G05 10) ...).
It sets up bindings for variables G and H, giving them a pair of gensyms as
initial values,  and then it evaluates the inner backquote `(LET ((,H ,10)) ...
etc ...).   This backquote produces (LET ((#:G05 10)) ...) which is your
output.  

Lisp doesn't have built-in ``do what I mean'' logic which would automatically
recognize that the newbie programmer's expression has produced data which looks
like Lisp code that maybe ought to be evaluated.

If you wanted it evaluated, why did you stick an extra level of backquote in
front of it? Backquote is a lot like regular quote: it suppresses evaluation. 
You didn't get the evaluation you wanted because you explicitly put in a
backquote to suppress it.

The expression `(LIST 1 2)  produces (LIST 1 2), just like '(LIST 1 2) does. If
you want to produce (1 2) then evaluate the expression (LIST 1 2), with no
quoting.

All you have to do is strip the outer backquote from your expression. Drop the
` from before (WITH-PS-GENSYMS ...), keeping the one before the inner (LET ...)
and then remove all occurences of ,'  (comma quote) so that ,',@body becomes
,@body, et cetera.
From: Pascal J. Bourguignon
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <8763ptbh7t.fsf@hubble.informatimago.com>
Kaz Kylheku <········@gmail.com> writes:

> Lisp doesn't have built-in ``do what I mean'' logic which would automatically
> recognize that the newbie programmer's expression has produced data which looks
> like Lisp code that maybe ought to be evaluated.

LE-LISP had it.

http://dli.iiit.ac.in/ijcai/IJCAI-77-VOL1/PDF/064a.pdf
http://www.ai.univ-paris8.fr/~hw/

http://lambda-the-ultimate.org/node/2907


While you would need heavy machinery for professionnal CL program,
something quite simple could be done to help newbies, with their FME
(Frequently Made Errors).


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

PLEASE NOTE: Some quantum physics theories suggest that when the
consumer is not directly observing this product, it may cease to
exist or will exist only in a vague and undetermined state.
From: Benjamin Teuber
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <ce1ca9ff-a684-4137-b468-0bf9beed329b@r66g2000hsg.googlegroups.com>
Actually I think the cl way of dealing with nested backquote kind of
sucks.
I really prefer named bq's, so you could e.g. write:

`(foo `1(bar ,x ,1y)) You get the idea.

By the way, after I "invented" that system, I did a bit of googling
for it and found out Drew McDermott had the same idea first =( and
implemented it in his YTools - which you might want to check out if
you find yourself hanging at nested-bq-problems often...

Cheers,
Benjamin
From: rock69
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <dc59c57e-439f-4c04-b78f-4776df5368fe@s50g2000hsb.googlegroups.com>
On 22 Ago, 22:01, Benjamin Teuber <······@web.de> wrote:
> Actually I think the cl way of dealing with nested backquote kind of
> sucks.
> I really prefer named bq's, so you could e.g. write:
>
> `(foo `1(bar ,x ,1y)) You get the idea.
>
> By the way, after I "invented" that system, I did a bit of googling
> for it and found out Drew McDermott had the same idea first =( and
> implemented it in his YTools - which you might want to check out if
> you find yourself hanging at nested-bq-problems often...
>
> Cheers,
> Benjamin

Thanks. I'll be checking that out as soon as possible.
From: Kent M Pitman
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <u3akvgiw9.fsf@nhplace.com>
Benjamin Teuber <······@web.de> writes:

> Actually I think the cl way of dealing with nested backquote kind of
> sucks.
> I really prefer named bq's, so you could e.g. write:
> 
> `(foo `1(bar ,x ,1y)) You get the idea.
> 
> By the way, after I "invented" that system, I did a bit of googling
> for it and found out Drew McDermott had the same idea first =( and
> implemented it in his YTools - which you might want to check out if
> you find yourself hanging at nested-bq-problems often...

There were a lot of backquote variants tried at first, and among the
variants were ones where the commas counted from the outside rather
than the inside.  That one failed, for example, because if you pasted
one expression inside another, its meaning got all messed up.
Similarly with the one you're suggesting, if you cut&paste parts of an
expression from one context to another, you're left with the need to
rationalize the containing labels, and it's easy to end up with nested
labels that are the same as the outer labels and need to be
renumbered.  I also think it's visually intrusive to see the digits
there.

But the reason CL provides user-definable macro capability is that
users don't always agree on these points.  It's easy to make something
an individual likes and sometimes even to attract an audience.  But
when you go to understand why the language as a whole doesn't do that,
the answer is usually that there is an additional requirement of broad
appeal.

Back in the days of TECO-based emacs, I had set up commas to flash
their matching backquote, just as parens flash their matching
paren. Many of my TECO macros were ported forward into Gnu Emacs when
that was created but I don't recall having seen the flashing comma
thing floating around today--maybe I've just missed it.  IMO, that's
the unobtrusive way to do it... In a modern environment one also might
want to make the backquoted area, when hovered over, lightly gray out
the inaccessible parts of the template or highlight the accesible
parts or some such.

After all, a similar argument could be made for parens.
1(defun fact 2( x 2)
   2(cond 3(4( zerop x 4) 1 3)
          3(t 4( * x 5( fact 6( - x 1 6)5)4)3)2)1)
Much clearer, no?  And yet, oddly enough, people prefer to just
count their parens by leaning heavily on editing tools and to 
assume it can be finessed by the human reader.

Normally, if you get to the level where you can't really guess just
by glancing at the general shape, without staring a lot, you've got 
some other problem with the presentation of your code.
From: Tobias C. Rittweiler
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <87sksuwx3r.fsf@freebits.de>
Kent M Pitman <······@nhplace.com> writes:

> Back in the days of TECO-based emacs, I had set up commas to flash
> their matching backquote, just as parens flash their matching
> paren. Many of my TECO macros were ported forward into Gnu Emacs when
> that was created but I don't recall having seen the flashing comma
> thing floating around today--maybe I've just missed it.  IMO, that's
> the unobtrusive way to do it... 

That's a nice idea! I think I'll give it a try.

  -T.
From: Kaz Kylheku
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <20080821220439.475@kkylheku.gmail.com>
On 2008-08-21, rock69 <···········@gmail.com> wrote:
> OK, I got it all wrong. It turns out I didn't need nested backquotes
> in the first place. This works fine:
>
> (defmacro ntimes (n &rest body)
>                    `(with-ps-gensyms (g h)
>                                      (let ((,h ,n))
>                                         (do ((,g 0 (+ ,g 1)))
>                                             ((>= ,g ,h))
>                                             ,@body))))

Still wrong. The macro now generates code which calls WITH-PS-GENSYMS.  But
WITH-PS-GENSYMS is a macro-expansion-time tool.

Never mind that, look at the botched logic. The G and H variables are bound
within the backquoted expression, i.e. within the code that the backquote is
trying to generate:

  `(with-ps-gensyms (g h) ...)

but they are also unquoted in that backquote:

   `(with-ps-gensyms ... (let ((,h ,n)) ... ,g ...))

this is incorrect scoping. The references to G and H are actually free
references from this backquote. The use of ,G and ,H within the backquote
requires the surrounding environment to have bindings for variables G and H,
without which it is erroneous to evaluate the backquote.

Did you actually try running this?
From: danb
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <fbed5913-1e44-42cb-9057-26e77ccfe040@m36g2000hse.googlegroups.com>
On Aug 21, 9:12 am, rock69 <···········@gmail.com> wrote:
> it still feels like something's missing.

The manuals tell you that the innermost backquote gets the
leftmost comma, but the point I didn't get right away was
that inner commas are "quoted", ie. they don't take effect
right away, because the outer backquotes are expanded first.

So if you have ,',foo inside two layers of backquotes, the
inner backquote gets the first comma, but it doesn't do anything
with it at first.  The outer backquote gets the second comma,
and is expanded first, so the second comma wants to evaluate
FOO.  In this case, it's preceeded by a regular quote, so
it doesn't do anything.  The net effect of ', is a no-op,
so ',foo returns the symbol FOO unevaluated.

Once the outer backquote has been evaluated, you can think of
the expression as still containing the inner backquote and
the first comma.  That expression is returned to the calling
environment, where the comma evaluates FOO.

I think that's the hardest part of learning backquotes.
Splicing in ,@ lists is easy, and everything else is just
repeated application of the rules.

--Dan

------------------------------------------------
http://www.prairienet.org/~dsb/

cl-match:  expressive pattern matching in Lisp
http://common-lisp.net/project/cl-match/
From: Kaz Kylheku
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <20080821175207.535@gmail.com>
On 2008-08-21, rock69 <···········@gmail.com> wrote:
> Tinkering a little, I've just discovered that it expands correctly by
> replacing ,,@body with ,',@body which seems logical of course :) yet

I suspect what trips up newbies is this psychology: it's easy to trick yourself
into regarding the unquote evaluation as mere variable substitution.  I.e. then
,,A looks like ``substitute variable A, and punch through two levels of
nesting''. But in fact ,,A means ``evaluate the expression ,A'' which means
``evaluate the expression arising from the evaluation of A''. Each comma is a
level of evaluation which may be undesireable and thus have to be suppressed by
a quote.


> it still requires one more evaluation step. In other words, it works
> only if I replace the invocation (ntimes 10 (format t "Hello World!~
> %")) with (eval (ntimes 10 (format t "Hello World!~%"))) which is of
> course a ridiculous thing to have to do, so I'm still pretty much
> stuck, only a little closer maybe to the solution.

That's probably because your NTIMES macro returns a WITH-PS-GENSYMS form. But
in fact WITH-PS-GENSYMS is intended to be a macro-writing helper; it should be
expanded within the body of NTIMES itself to generate the code of NTIMES; it's
not supposed to be the code that NTIMES generates.

You don't need the nested backquote at all:

  (macrolet ...
    (ntimes (n &rest body)
      (with-ps-gensyms (g h)
        `(let ((,h ,n))
	   (do  ...
	     ,@body)))))


NTIMES doesn't produce a WITH-PS-GENSYMS form, it uses WITH-PS-GENSYMS
for its implementation. If you didn't have WITH-PS-GENSYMS, you would write:

  (macrolet ...
    (ntimes (n &rest body)
      (let ((g (gensym))
            (h (gensym)))
         `(let ((,h ,n))
	    (do ...
	      ,@body)))))


WITH-PS-GENSYMS gives you a shorthand for creating a farm variables that
hold gensyms.
From: Pascal J. Bourguignon
Subject: Re: Nested bacquotes are so hard (at least for me :) )!
Date: 
Message-ID: <873akydyh8.fsf@hubble.informatimago.com>
rock69 <···········@gmail.com> writes:

> I was doing some experimenting with MACROLET, just to figure out how
> it works a little better, but I can't get the following code to work.
> It only prints "Hello World!" once instead of 10 times. There's no
> specific goal for this code. I was just experimenting for learning
> purposes only.
>
> (macrolet ((with-ps-gensyms ((&rest names) &body body)
> 			    `(let ,(loop for n in names collect `(,n (gensym)))
> 			       ,@body))
> 	   (ntimes (n &rest body)
> 		   `(with-ps-gensyms (g h)
> 				     `(let ((,h ,,n))
> 					(do ((,g 0 (+ ,g 1)))
> 					    ((>= ,g ,h))
> 					    ,,@body)))))
> 	  (ntimes 10 (format t "Hello World!~%")))

Well, if backquotes are so hard for you why do you use them?
It's easier to test and debug macros when defined with defmacro.

(defmacro with-ps-gensyms ((&rest names) &body body)
  (list* 'let
         (loop for n in names collect (list n '(gensym)))
         body))

(macroexpand '(with-ps-gensyms (a b c) (list 'list a b c)))
--> (LET ((A (GENSYM)) (B (GENSYM)) (C (GENSYM))) (LIST 'LIST A B C))

(with-ps-gensyms (a b c) (list 'list a b c))
--> (LIST #:G29968 #:G29969 #:G29970)


(defmacro ntimes (n &rest body)
  (with-ps-gensyms (g h)
    (list 'let
          (list (list h n))
          (list* 'do
                 (list (list g '0 (list '+ g '1))) 
                 (list (list '>= g h))
                 body))))

(macroexpand '(ntimes 10 (format t "Hello World!~%")))
--> (LET ((#:G30014 10)) (DO ((#:G30013 0 (+ #:G30013 1))) ((>= #:G30013 #:G30014)) (FORMAT T "Hello World!~%")))

(ntimes 10 (format t "Hello World!~%"))
prints:
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
--> NIL


(macrolet ((with-ps-gensyms ((&rest names) &body body)
             (list* 'let
                    (loop for n in names collect (list n '(gensym)))
                    body))
           (ntimes (n &rest body)
             (with-ps-gensyms (g h)
               (list 'let
                     (list (list h n))
                     (list* 'do
                            (list (list g '0 (list '+ g '1))) 
                            (list (list '>= g h))
                            body)))))
  (ntimes 10 (format t "Hello World!~%")))
prints:
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
--> NIL




-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Specifications are for the weak and timid!"