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.