Based on the documentation, I thought that the right answer would be `(list (gensym))` but that didn't work -- hopefully someone else knows.
Sam On Tue, Jun 23, 2015 at 4:43 PM, Thomas Dickerson <thomas_dicker...@brown.edu> wrote: > I thought that might be the case, but the documentation is pretty dense (and > self-referential), so it's not clear what the correct value for that > argument is. > > Thomas Dickerson > > Brown University > Department of Computer Science > 115 Waterman St, 4th Floor > Providence, RI 02912 > > 802-458-0637 > > On Tue, Jun 23, 2015 at 3:57 PM, Sam Tobin-Hochstadt <sa...@cs.indiana.edu> > wrote: >> >> To fix your last issue, you probably want to provide a different value as >> the `context-v` argument (the 2nd one) to `local-expand`. >> >> Sam >> >> On Tue, Jun 23, 2015 at 3:46 PM Thomas Dickerson >> <thomas_dicker...@brown.edu> wrote: >>> >>> Okay - for posterity's sake, here's an updated version of Alex's code >>> that supports nested Loop/Accum, and doesn't leave any "syntactic residue" >>> after expansion. This is now what I set out to accomplish with my original >>> set of questions: >>>> >>>> #lang racket/base >>>> >>>> (require racket/stxparam >>>> (for-syntax racket/base >>>> >>>> racket/set >>>> racket/syntax >>>> syntax/parse >>>> syntax/stx >>>> syntax/context)) >>>> >>>> (define-syntax Loop >>>> (lambda (stx) >>>> (syntax-parse stx >>>> [(Loop accum-id:id up-to-expr:expr body:expr ...+) >>>> (let* ([defs (syntax-local-make-definition-context)] >>>> [ctx (generate-expand-context)]) >>>> (syntax-local-bind-syntaxes >>>> (list #'accum-id) >>>> (local-transformer-expand >>>> #'(let ([vars (mutable-set)]) >>>> (lambda ([stx #f]) >>>> (if (syntax? stx) >>>> (syntax-parse stx >>>> [(accum-id x:id dx:expr) >>>> (set-add! vars (syntax-local-introduce #'x)) >>>> >>>> >>>> #'(set! x (+ x dx))]) >>>> >>>> vars))) 'expression null) defs) >>>> (internal-definition-context-seal defs) >>>> (with-syntax* ([(body ...) >>>> (stx-map >>>> (lambda (body) >>>> (with-syntax ([body body]) >>>> (local-expand #'body ctx null defs))) >>>> #'(body ...))] >>>> [(init ...) >>>> (map >>>> (lambda (var) >>>> (with-syntax ([var (syntax-local-introduce >>>> var)]) #'(set! var 0))) >>>> (set->list >>>> ((syntax-local-value >>>> (internal-definition-context-apply defs >>>> #'accum-id) >>>> #f defs))))]) >>>> #'(let ([up-to up-to-expr]) >>>> >>>> >>>> (letrec >>>> ([loop >>>> (lambda (n) >>>> body ... >>>> >>>> (let ([n (add1 n)]) >>>> (if (< n up-to) >>>> (loop n) >>>> (void))))]) >>>> init ... >>>> (loop 0)))))] >>>> >>>> >>>> [(Loop up-to-expr:expr body:expr ...+) >>>> >>>> (with-syntax >>>> ([Accum (datum->syntax stx 'Accum)]) >>>> #'(Loop Accum up-to-expr body ...))]))) >>>> >>>> (let ([x (void)] [y (void)] [z (void)]) >>>> (Loop 2 >>>> (let ([dx 1] [dy 2] [dz 3]) >>>> (Accum x dx) >>>> (Loop AccumInner 2 >>>> >>>> >>>> (printf "x = ~v, y = ~v, z = ~v\n" x y z) >>>> >>>> (Accum y dy) >>>> (AccumInner z dz))))) >>> >>> >>> One last question - the change to using local-expand meant that the loop >>> body was no longer happy accepting define-values forms and raised "Not in a >>> definition context" errors. I can use let to accomplish the same thing >>> without any problems, but if someone could explain what changes would need >>> to be made to the local-expand call for that to work, I'd be grateful (for >>> my own understanding). >>> >>> >>> Thomas Dickerson >>> >>> Brown University >>> Department of Computer Science >>> 115 Waterman St, 4th Floor >>> Providence, RI 02912 >>> >>> 802-458-0637 >>> >>> On Tue, Jun 23, 2015 at 11:17 AM, Thomas Dickerson >>> <thomas_dicker...@brown.edu> wrote: >>>> >>>> On Tuesday, June 23, 2015 at 8:30:32 AM UTC-4, Matthew Flatt wrote: >>>> > Providing #f as the third argument to `local-expand` means that >>>> > >>>> > (+ i j) >>>> > >>>> > is expanded only as far as exposing the primitive function-call form, >>>> > also known as `#%plain-app`: >>>> > >>>> > (#%plain-app + i j) >>>> > >>>> > When `i` is encountered later, there's no binding in the compile-time >>>> > environment, because the internal-definition context has been >>>> > discarded as the `my-def-stx` macro returned. >>>> > >>>> > Probably you want to replace the `#f` with `null` (which means "expand >>>> > without stopping"). >>>> Got it - this makes sense, thanks. >>>> >>>> > Another possibility is to expand to a >>>> > `letrec-syntaxes+values` form to bind `i` and `j`. >>>> >>>> This is actually what I'm trying to avoid - see the earlier note on why >>>> I need a solution that won't leave behind empty (let-values () ...) forms >>>> (or any other Racket-specific forms) in the output syntax. >>>> >>>> > At Tue, 23 Jun 2015 02:13:19 -0400, Thomas Dickerson wrote: >>>> > > I seem to be missing some key ingredient here. The following really >>>> > > simply >>>> > > test-case, using let-syntaxes, works as expected: >>>> > > >>>> > > > (define-syntax my-def-stx >>>> > > > (lambda (stx) >>>> > > > (syntax-case stx (my-def-stx) >>>> > > > [(my-def-stx (id ...) rhs expr) >>>> > > > #'(let-syntaxes ([(id ...) rhs]) expr)]))) >>>> > > > >>>> > > > (my-def-stx >>>> > > > (i j) (values (lambda (stx) #'3) (lambda (stx) #'4)) >>>> > > > (+ i j)) >>>> > > > >>>> > > Trying the same thing, but with this: >>>> > > >>>> > > > (require (for-syntax syntax/context)) >>>> > > > (define-syntax my-def-stx >>>> > > > (lambda (stx) >>>> > > > (syntax-case stx (my-def-stx) >>>> > > > [(my-def-stx (id ...) rhs expr) >>>> > > > (let* ([intdef (syntax-local-make-definition-context)] >>>> > > > [ctx (generate-expand-context)]) >>>> > > > (syntax-local-bind-syntaxes (syntax->list #'(id ...)) >>>> > > > (local-transformer-expand #'rhs 'expression null) intdef) >>>> > > > (internal-definition-context-seal intdef) >>>> > > > (local-expand #'expr ctx #f intdef))]))) >>>> > > > >>>> > > > (my-def-stx >>>> > > > (i j) (values (lambda (stx) #'3) (lambda (stx) #'4)) >>>> > > > (+ i j)) >>>> > > > >>>> > > instead, gives me "i: undefined; cannot reference an identifier >>>> > > before its >>>> > > definition". >>>> > > >>>> > > Thomas Dickerson >>>> > > >>>> > > Brown University >>>> > > Department of Computer Science >>>> > > 115 Waterman St, 4th Floor >>>> > > Providence, RI 02912 >>>> > > >>>> > > 802-458-0637 >>>> > > >>>> > > On Mon, Jun 22, 2015 at 11:39 PM, Matthew Flatt <mfl...@cs.utah.edu> >>>> > > wrote: >>>> > > >>>> > > > Probably you don't want to work with namespaces, which are >>>> > > > intended more >>>> > > > for run-time reflection. >>>> > > > >>>> > > > For an example of turning internal definitions into >>>> > > > 'letrec-syntaxes+values', try the implementation of >>>> > > > 'racket/block'. >>>> > > > >>>> > > > > On Jun 23, 2015, at 10:06 AM, Thomas Dickerson < >>>> > > > thomas_dicker...@brown.edu> wrote: >>>> > > > > >>>> > > > > Update / addendum: I was also able to fairly trivially extend >>>> > > > > Alex's >>>> > > > code using let-syntax to have the more hygienic behavior for where >>>> > > > Accum >>>> > > > is/is-not visible, but let-syntax ends up leaving an additional >>>> > > > layer of >>>> > > > empty (let-values() ...) behind. >>>> > > > > >>>> > > > > The documentation for let-syntax makes the following claim - >>>> > > > > "The >>>> > > > evaluation of each trans-expr is parameterized to set >>>> > > > current-namespace to >>>> > > > a namespace that shares bindings and variables with the namespace >>>> > > > being >>>> > > > used to expand the let-syntax form, except that its base phase is >>>> > > > one >>>> > > > greater." which seems very much related to what I'd like to >>>> > > > accomplish (and >>>> > > > Shriram's suggestion that I mentioned in the original post); >>>> > > > however, I see >>>> > > > no evidence of this actually taking place in the Racket >>>> > > > source-code, it >>>> > > > just appears to desugar, with very few bells and whistles, to >>>> > > > letrec-syntaxes+values which evidently is implemented in the C >>>> > > > code. >>>> > > > Digging into syntax-parameterize shows that, unsurprisingly, this >>>> > > > is also >>>> > > > how syntax-parameterize gets desugared, with a few more bells and >>>> > > > whistles. >>>> > > > > >>>> > > > > So I guess at this point the remainder of my question boils down >>>> > > > > to >>>> > > > this: can someone offer any insight into the process of turning >>>> > > > macros >>>> > > > which are introduced by let-syntax or equivalent into macros which >>>> > > > are >>>> > > > introduced implicitly by an internal-definition-context argument >>>> > > > to >>>> > > > local-expand, or by explicit namespace manipulation as hinted at >>>> > > > in the >>>> > > > let-syntax documentation (but which I can't turn up anywhere). >>>> > > > > >>>> > > > >> On Monday, June 22, 2015 at 5:35:50 PM UTC-4, Thomas Dickerson >>>> > > > >> wrote: >>>> > > > >> 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. >>>> > > > >>>> > > >>>> > > -- >>>> > > 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. >>>> >>> >>> -- >>> 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. > > > -- > 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. -- 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.