[plt-scheme] Help with a macro

From: Felix Klock's PLT scheme proxy (pltscheme at pnkfx.org)
Date: Mon Oct 3 11:24:54 EDT 2005


On Oct 3, 2005, at 9:40 AM, 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?

[[ my macro-fu is not as strong as that of others in my lab, but I  
believe this does explain your problem ]]


In the expression #'(printf "~a" it)), the identifier is marked as  
belonging to the form #'(a-loop 9 (printf "~a" it))

When your macro expands, it turns into a series of nested bindings  
for fresh occurrences of 'it. But when the expander plugs in the  
expression #'(printf "~a" it), the #'it there still carries the marks  
that associate it with that first outer occurrence of #'(a-loop 9  
(printf "~a" it)); NOT any of the occurrences that are constructed  
within the macro body.

  Like so:

(let ((it-1 9))
     (printf "~a" it-1)
     (let ((it-2 8))
            (printf "~a" it-1)
            (let ((it-3 7))
                     (printf "~a" it-1)
                     (let ((it-4 6))

Don't use datum->syntax-object unless you really know what you are  
doing.  (That's why I rarely use it -- I rarely know what I'm doing.)


Posted on the users mailing list.