[plt-scheme] Help with a macro

From: Evan Farrer (farrer at cs.utah.edu)
Date: Mon Oct 3 12:14:48 EDT 2005

Matthew,

Thanks that gives me what I need.

Evan

On Mon, Oct 03, 2005 at 09:35:13AM -0600, Matthew Flatt wrote:
> At Mon, 3 Oct 2005 07:40:47 -0600, Evan Farrer wrote:
> > (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 ...))))))]))
> 
> Expanding to a use of a non-hygienic macro is troublesome, because the
> macro is going to grab some part of its input to give context to the
> non-hygienic identifier. In this case, `a-loop' uses the context of
> `count'.
> 
> On the first iteration, `count' has the context that you want. On the
> second iteration, though, `count' has the context of `#,next', which is
> not what you want.
> 
> Using `#,(datum->syntax-object (syntax count) next)' avoids the
> problem, at least for your example, by transferring the context of the
> original `count' to each `next'.
> 
> Better yet, avoid the non-hygienic identifier. Using a syntax
> parameter, you can also avoid making code that uses `a-loop' supply an
> identifier to bind. Instead you end up with a single `it' binding whose
> meaning is adjusted by `a-loop':
> 
>  (require (lib "stxparam.ss"))
> 
>  (define-syntax-parameter it (lambda (stx)
>                               (raise-syntax-error
>                                #f
>                                "only valid in `a-loop'"
>                                stx)))
> 
>  (define-syntax (a-loop stx)
>   (syntax-case stx (for)
>     [(_ count body ...)
>      (let ([done (equal? 0 (syntax-object->datum #'count))]
>            [next (sub1 (syntax-object->datum #'count))])
>        #`(let ([itid count])
>            ;; Map `it' to `itid' for the body:
>            (syntax-parameterize ([it (make-rename-transformer 
>                                       (quote-syntax itid))])
>              #,(if done
>                    #'(begin body ...)
>                    #`(begin
>                        body ...
>                        (_ #,next body ...))))))]))
> 
> 
>  > (a-loop 9 (display it))
>  9876543210
>  > it
>  it: only valid in `a-loop' in: it
> 
> 
> Matthew
> 
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme


Posted on the users mailing list.