[plt-scheme] Help with a macro

From: Matt Jadud (mcj4 at kent.ac.uk)
Date: Mon Oct 3 10:26:27 EDT 2005

Hi Evan,

While this does not address your question, you are trying to do 
something I've tried to eliminate from my macro-fu, which is the 
introduction of new identifiers into the macro's scope. It is, generally 
speaking, easier to let the programmer provide the identifier.

For example, you could compress your macro quite a bit by expanding the 
loop into, well, a Scheme loop (well, a named 'let', anyway).

(define-syntax (a-loop-too stx)
   (syntax-case stx ()
     [(_ (index count) bodies ...)
      #`(let loop ([#,(syntax index) #,(syntax count)])
          (unless (zero? #,(syntax index))
            #,@(syntax->list (syntax (bodies ...)))
            (loop (sub1 #,(syntax index)))))]
     ))

Note how I've forced the macro writer to provide the loop counter, 
instead of having the identifier magically "appear" in the context of 
the macro. This makes it obvious to a programmer using your macro (or to 
yourself a few days, weeks, or months later) where the counter variable 
comes from. It also becomes easier to nest the macro as well, as I can say

(a-loop-too (a 5)
   (a-loop-too (b 4)
     (printf "~a ~a~n" a b)))

and it will work; without the use of "gensym", it is possible you would 
have collisions on the identifier "it".

As I said, that doesn't answer your question, but gives you some 
food-for-thought; my apologies if I'm completely in left-field, or this 
generally isn't applicable.

M


Evan Farrer wrote:
> I've run into a problem with a macro that I'm writing.  I've come up with a simple example that demonstrates the behavior that I'm seeing.
> 
> (define-syntax (a-loop stx)
>   (syntax-case stx (for)
>                [(_ count body ...)
>                (with-syntax ([itid (datum->syntax-object (syntax count) 'it)])     
>                             (let ([done (equal? 0 (syntax-object->datum #'count))]
>                                         [next (sub1 (syntax-object->datum #'count))])
>                               #`(let ([itid count])
>                                   #,(if done
>                                       #'(begin body ...)
>                                       #`(begin
>                                           body ...
>                                           (_ #,next body ...))))))]))
> 
> If I call the following like:
>   (a-loop 9 (printf "~a" it))
> 
> I get a series of 9's  I'd expect "9876543210".  I've tried running it under the expander language and from what I can see, everything should be working.  Can anyone enlighten me as to where my thinking is wrong, and how this should be implemented?
> 
> Thanks,
> 
> Evan
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme


Posted on the users mailing list.