<div dir="ltr">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.<div>
<br></div><div><a href="https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/layout-types.rkt">https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/layout-types.rkt</a><br></div><div><a href="https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/layout.rkt">https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/layout.rkt</a><br>
</div><div><a href="https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/parser.rkt">https://github.com/RayRacine/racketlib/blob/mapred/RpR/format/parser.rkt</a><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Wed, Jan 16, 2013 at 10:33 AM, Danny Yoo <span dir="ltr"><<a href="mailto:dyoo@hashcollision.org" target="_blank">dyoo@hashcollision.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Wed, Jan 16, 2013 at 7:24 AM, Tim Brown <<a href="mailto:tim.brown@cityc.co.uk">tim.brown@cityc.co.uk</a>> wrote:<br>
> Folks,<br>
><br>
> I would like to write a module that uses a macro to transform "define"s<br>
> and accumulate a value based on those transformations.<br>
><br>
> In a fairly simple way, I want to do something like the below. However, it<br>
> seems the module-begin is being transformed before the my-defines. How do<br>
> I get counter to be incremented before I need it?<br>
<br>
</div>The transformation happens top-down, so you'll see that the body of<br>
your program expands in the following steps (to a first<br>
approximation):<br>
<br>
<br>
(#%your-module-begin (your-define woo 2))<br>
<br>
==><br>
<br>
(#%racket-module-begin (your-define woo 2)<br>
(define defines-counter 0)<br>
(provide defines-counter))<br>
<br>
==><br>
<br>
(#%racket-module-begin (racket-define woo 2)<br>
(define defines-counter 0)<br>
(provide defines-counter))<br>
<br>
<br>
One possible workaround is the the following: add one level of<br>
indirection in installing the value of the defines-counter. You can<br>
do something like:<br>
<br>
(define-syntax (get-counter stx)<br>
(datum->syntax stx counter))<br>
<br>
and use (get-counter) in place of #,counter in your module-begin.<br>
This way, we delays the lookup of counter until the macro expander<br>
finally reaches that expression, and by that time, it should have hit<br>
all the defines already.<br>
<br>
<br>
If you need to control the order of expansion more explicitly, you may<br>
need to look into local-expand:<br>
<br>
<a href="http://docs.racket-lang.org/reference/stxtrans.html#(def._((quote._~23~25kernel)._local-expand))" target="_blank">http://docs.racket-lang.org/reference/stxtrans.html#(def._((quote._~23~25kernel)._local-expand))</a><br>
<br>
----<br>
<br>
Modified code below:<br>
<br>
#lang racket/base<br>
<div class="im"><br>
(provide (except-out (all-from-out racket) #%module-begin define)<br>
(rename-out (module-begin #%module-begin) (my-define define)))<br>
<br>
</div> (require (for-syntax racket/base<br>
<div class="im"> syntax/parse))<br>
(define-for-syntax counter 0)<br>
<br>
(define-syntax (my-define stx)<br>
(syntax-parse<br>
stx<br>
[(_ i v) (set! counter (add1 counter)) #`(define i v)]<br>
[(_ (i args ...) v ...+) (set! counter (add1 counter))<br>
#`(define (i args ...) v ...)]))<br>
<br>
</div> (define-syntax (get-counter stx )<br>
(datum->syntax stx counter))<br>
<div class="im"><br>
(define-syntax (module-begin stx)<br>
(syntax-parse<br>
stx<br>
[(_ expr ...)<br>
#`(#%module-begin expr ...<br>
</div> (define defines-count (get-counter))<br>
(provide defines-count))]))<br>
<div class="HOEnZb"><div class="h5">____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
</div></div></blockquote></div><br></div>