[racket] variables within macros

From: Ray Racine (ray.racine at gmail.com)
Date: Wed Jan 16 10:56:47 EST 2013

On the topic of "state" propagation across macros by extending the
expansion environment (or whatever the terminology would be).    I have an
example where a macro is used to define a layout of a fixed offset text
file.  Then a second macro expands into a mini field parser based on the
layout definition.   Frankly my first macro beyond a basic syntax-rules
sort, so it's rough and assuredly less than optimal.  It can be found here.

https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/layout-types.rkt
https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/layout.rkt
https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/parser.rkt


On Wed, Jan 16, 2013 at 10:33 AM, Danny Yoo <dyoo at hashcollision.org> wrote:

> On Wed, Jan 16, 2013 at 7:24 AM, Tim Brown <tim.brown at cityc.co.uk> wrote:
> > Folks,
> >
> > I would like to write a module that uses a macro to transform "define"s
> > and accumulate a value based on those transformations.
> >
> > In a fairly simple way, I want to do something like the below. However,
> it
> > seems the module-begin is being transformed before the my-defines. How do
> > I get counter to be incremented before I need it?
>
> The transformation happens top-down, so you'll see that the body of
> your program expands in the following steps (to a first
> approximation):
>
>
> (#%your-module-begin (your-define woo 2))
>
> ==>
>
> (#%racket-module-begin (your-define woo 2)
>                                     (define defines-counter 0)
>                                     (provide defines-counter))
>
> ==>
>
> (#%racket-module-begin (racket-define woo 2)
>                                     (define defines-counter 0)
>                                     (provide defines-counter))
>
>
> One possible workaround is the the following: add one level of
> indirection in installing the value of the defines-counter.  You can
> do something like:
>
>     (define-syntax (get-counter stx)
>        (datum->syntax stx counter))
>
> and use (get-counter) in place of #,counter in your module-begin.
> This way, we delays the lookup of counter until the macro expander
> finally reaches that expression, and by that time, it should have hit
> all the defines already.
>
>
> If you need to control the order of expansion more explicitly, you may
> need to look into local-expand:
>
>
> http://docs.racket-lang.org/reference/stxtrans.html#(def._((quote._~23~25kernel)._local-expand))
>
> ----
>
> Modified code below:
>
>   #lang racket/base
>
>   (provide (except-out (all-from-out racket) #%module-begin define)
>            (rename-out (module-begin #%module-begin) (my-define define)))
>
>   (require (for-syntax racket/base
>                        syntax/parse))
>   (define-for-syntax counter 0)
>
>   (define-syntax (my-define stx)
>     (syntax-parse
>         stx
>       [(_ i v) (set! counter (add1 counter)) #`(define i v)]
>       [(_ (i args ...) v ...+) (set! counter (add1 counter))
>                                #`(define (i args ...) v ...)]))
>
>   (define-syntax (get-counter stx )
>     (datum->syntax stx counter))
>
>   (define-syntax (module-begin stx)
>     (syntax-parse
>         stx
>       [(_ expr ...)
>        #`(#%module-begin expr ...
>                          (define defines-count (get-counter))
>                          (provide defines-count))]))
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130116/9857d8c6/attachment-0001.html>

Posted on the users mailing list.