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.

Reply via email to