Thanks for the effort that went into figuring that out! A couple first thoughts 
on the implementation:
To first order, this is exactly what I want to be able to do (and it elegantly 
avoids local-expand by reasoning about expansion order); however, as a general 
pattern, it's a bit unhygienic in that Accum is now in the global namespace, 
which precludes using it as a child macro for other constructs, and prevents 
specific instantiations of Loop from requesting a different name for Accum to 
cooperate in nested loops.

I also noticed that (syntax-parameterize) isn't totally transparent in the 
expanded syntax - it leaves a bunch of empty (let-values () ...) behind, which 
is fine for Racket, but problematic in my target use-case of emitting something 
which ultimately needs to be an entirely different language. This is why my 
experiments have all involved local-expand - I want to introduce expand-time 
names without introducing wrapping let-syntaxes (or similar) forms around my 
body code.


On Saturday, June 20, 2015 at 2:24:40 PM UTC-4, Alex Knauth wrote:
> On Jun 19, 2015, at 7:44 PM, Thomas Dickerson <thomas_dicker...@brown.edu> 
> wrote:
> 
> > I was intending for that example to have the variables be defined outside 
> > the macro, but being able to create the (set! ...) forms outside should 
> > mean I could also hypothetically create let/define-values forms. This is 
> > why I originally specified being able to effect generation of both prologue 
> > + epilogue code.
> 
> I figured this out for code that will be expanded after the body:
> 
> #lang racket/base
> 
> (require racket/stxparam
>          (for-syntax racket/base
>                      syntax/parse
>                      racket/set
>                      ))
> 
> ;; (syntax-parameter-value vars) : (U #f (MutableSetof Identifier))
> (define-syntax-parameter vars #f)
> 
> (define-syntax Accum
>   (lambda (stx)
>     (syntax-parse stx
>       [(Accum x:id dx:expr)
>        (define vs (syntax-parameter-value #'vars))
>        (unless (set-mutable? vs)
>          (raise-syntax-error #f "cannot be used outside Loop" stx))
>        (set-add! vs (syntax-local-introduce #'x))
>        #'(set! x (+ x dx))])))
> 
> (define-syntax set-accums-zero!
>   (syntax-parser
>     [(set-accums-zero!)
>      #:with [x ...]
>      (map syntax-local-introduce (set->list (syntax-parameter-value #'vars)))
>      #'(begin (set! x 0) ...)]))
> 
> (define-syntax Loop
>   (syntax-parser
>     [(Loop up-to-expr:expr body:expr ...+)
>      #'(syntax-parameterize ([vars (mutable-set)])
>          (let ([up-to up-to-expr])
>            (letrec
>                ([loop
>                  (lambda (n)
>                    body
>                    ...
>                    (if (< n up-to)
>                        (loop (add1 n))
>                        (void)))])
>              (set-accums-zero!)
>              (loop 0))))]))
> 
> (let ([x "x"] [y "y"] [z "z"])
>   (Loop 10
>         (begin
>           (define-values 
>             [dx dy dz] 
>             (values 1 2 3))
>           (printf "x = ~v, y = ~v, z = ~v\n" x y z)
>           (Accum x dx)
>           (Accum y dy)
>           (Accum z dz))))
> 
> To generate a let outside of that you’d probably need to do some kind of 
> local-expand, but I’m not sure.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to