[plt-scheme] Help with a macro
Evan-
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 ]]
Hypothesis:
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))
(begin
(printf "~a" it-1)
(let ((it-2 8))
(begin
(printf "~a" it-1)
(let ((it-3 7))
(begin
(printf "~a" it-1)
(let ((it-4 6))
....
)))))))
Conclusion:
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.)
-Felix