Wow, so block is currently buggy?! On Sun, Jun 7, 2020 at 3:31 PM Michael Ballantyne < [email protected]> wrote:
> Hah! You're right. The arrow points to the inner definition. But it's even > worse than that---the value comes from the outer definition! At least for > `block`, which is what I'm testing with as I haven't copied down your code. > Try this: > > #lang racket > > (require racket/block) > > (define-syntax-rule (m) (displayln 'old)) > > (let () > (block (m)) > (define-syntax-rule (m) 'new) > (void)) > > (and with your macro rather than block) > > On Sunday, June 7, 2020 at 4:27:24 PM UTC-6, Sorawee Porncharoenwase wrote: >> >> Perhaps I missed something, but the error in the first example is because >> there’s no expression at the end of let. If I use this code instead, it >> seems to work fine, with the arrow of m pointing to the “new” one. >> >> (define-syntax-rule (m) 'old) >> >> (let () >> (list+ (m)) >> (define-syntax-rule (m) 'new) >> (void)) >> >> The second example perfectly shows why I need >> internal-definition-context-track, however. Thank you very much. >> >> On Sun, Jun 7, 2020 at 7:51 AM Michael Ballantyne <[email protected]> >> wrote: >> >>> > I am unable to come up with a program where this difference is >>> significant though >>> >>> Here's an example: >>> >>> (define-syntax-rule (m) 'old) >>> >>> (let () >>> ($list >>> (m)) >>> (define-syntax-rule (m) 'new)) >>> >>> >>> > So I am curious why internal-definition-context-track is needed. >>> >>> A similar example shows the need here: >>> >>> ($list >>> (define-syntax-rule (m) 5) >>> (m)) >>> >>> Without `internal-definition-context-track` you'll miss the arrow for >>> `m`. While `m` does indeed get rebound in the `letrec-syntaxes+values`, >>> that binding has an extra scope, so the reference to `m` (recorded in an >>> `'origin` property on `5`) doesn't match. >>> >>> >>> >>> On Sunday, June 7, 2020 at 12:18:26 AM UTC-6, Sorawee Porncharoenwase >>> wrote: >>>> >>>> Thank you so much, Michael! This is very helpful. >>>> >>>> I can see that when this form is used within another internal >>>> definition context, then my version and your version will expand in >>>> different order, and I agree that yours makes more sense. I am unable to >>>> come up with a program where this difference is significant though (e.g., >>>> one fails while the other doesn’t). “so that names bound by later >>>> definitions are available” seems to suggest that things like this is not >>>> supposed to work on my version: >>>> >>>> (let () >>>> ($list (define (f x) (g x)) >>>> (println f)) >>>> (define (g x) x) >>>> (void)) >>>> >>>> but it actually does… >>>> >>>> I also have another question. When should I use >>>> internal-definition-context-track? Normally, internal definitions are >>>> expanded into letrec-syntaxes+values, so the bindings don’t actually >>>> disappear. So I am curious why internal-definition-context-track is >>>> needed. >>>> >>>> Thanks again. >>>> >>>> On Sat, Jun 6, 2020 at 8:21 AM Michael Ballantyne < >>>> [email protected]> wrote: >>>> >>>>> Explicitly expanding `e` would ensure that the expansion work only has >>>>> to happen once, rather than twice. Even so, the fully-expanded syntax will >>>>> be expanded again in `syntax-local-bind-syntaxes` and in the expansion. >>>>> >>>>> As far as I've seen, the only thing that liberal define contexts >>>>> control is whether definitions of functions that accept keyword arguments >>>>> expand to a normal `define-values` with runtime handling of keywords, or >>>>> expand to a collection of macros and function definitions that allow a >>>>> more >>>>> efficient calling convention for first-order calls. The latter expansion >>>>> doesn't work for contexts like `class` where function definitions are >>>>> re-interpreted in a way that adds indirection, so it is only enabled in >>>>> contexts that opt-in. >>>>> >>>>> I see more bug in your macro: as its very first task, it should check >>>>> if `(syntax-local-context)` is `'expression`. If not, it should expand to >>>>> `(#%expression <the-original-call>)`. This ensures that its expansion is >>>>> delayed until the second pass of the surrounding definition context so >>>>> that >>>>> names bound by later definitions are available. >>>>> >>>>> On Saturday, June 6, 2020 at 4:15:00 AM UTC-6, Sorawee Porncharoenwase >>>>> wrote: >>>>>> >>>>>> Ah, apparently I need syntax-local-identifier-as-binding. Here’s a >>>>>> revised code that passes the tests. >>>>>> >>>>>> (begin-for-syntax >>>>>> (define ((do-it gs ctx) e) >>>>>> (let loop ([e e]) >>>>>> (define e-expanded (local-expand e >>>>>> (list gs) >>>>>> (list #'begin >>>>>> #'define-syntaxes >>>>>> #'define-values) >>>>>> ctx)) >>>>>> (syntax-parse e-expanded >>>>>> #:literals (begin define-syntaxes define-values) >>>>>> [(begin body ...) #`(begin #,@(map loop (attribute body)))] >>>>>> [(define-values (x ...) e) >>>>>> #:with (x* ...) (map syntax-local-identifier-as-binding >>>>>> (attribute x)) >>>>>> (syntax-local-bind-syntaxes (attribute x) #f ctx) >>>>>> #'(define-values (x* ...) e)] >>>>>> [(define-syntaxes (x ...) e) >>>>>> #:with (x* ...) (map syntax-local-identifier-as-binding >>>>>> (attribute x)) >>>>>> (syntax-local-bind-syntaxes (attribute x) #'e ctx) >>>>>> #'(define-syntaxes (x* ...) e)] >>>>>> [e #'(set! acc (cons e acc))])))) >>>>>> >>>>>> Still not sure if there’s still anything wrong. In particular, do I >>>>>> need to expand e in define-syntaxes? And do I need to use >>>>>> prop:liberal-define-context for gs? (I don’t understand what liberal >>>>>> expansion is even after reading the docs several times) Both of these are >>>>>> done in the implementation of block, but without them, it seems to >>>>>> work equally well. >>>>>> >>>>>> On Fri, Jun 5, 2020 at 6:30 PM Sorawee Porncharoenwase < >>>>>> [email protected]> wrote: >>>>>> >>>>>>> Hi Racketeers, >>>>>>> >>>>>>> I’m creating a macro that collects values in the internal-definition >>>>>>> context. E.g., >>>>>>> >>>>>>> ($list >>>>>>> 1 >>>>>>> (define x 2) >>>>>>> x) >>>>>>> >>>>>>> should evaluate to '(1 2). >>>>>>> >>>>>>> Here’s my implementation, and it kinda works: >>>>>>> >>>>>>> #lang racket >>>>>>> >>>>>>> (begin-for-syntax >>>>>>> (define ((do-it gs ctx) e) >>>>>>> (let loop ([e e]) >>>>>>> (define e-expanded (local-expand e (list gs) #f ctx)) >>>>>>> (syntax-case e-expanded (begin define-syntaxes define-values) >>>>>>> [(begin body ...) >>>>>>> #`(begin #,@(map loop (syntax->list #'(body ...))))] >>>>>>> [(define-values ids e) >>>>>>> (begin >>>>>>> (syntax-local-bind-syntaxes (syntax->list #'ids) #f ctx) >>>>>>> e-expanded)] >>>>>>> [(define-syntaxes ids e) >>>>>>> (begin >>>>>>> (syntax-local-bind-syntaxes (syntax->list #'ids) #'e ctx) >>>>>>> #'(begin))] >>>>>>> [e #'(set! acc (cons e acc))])))) >>>>>>> >>>>>>> (define-syntax ($list stx) >>>>>>> (define gs (gensym)) >>>>>>> (define ctx (syntax-local-make-definition-context)) >>>>>>> (syntax-case stx () >>>>>>> [(_ body ...) >>>>>>> #`(let ([acc '()]) >>>>>>> #,@(map (do-it gs ctx) (syntax->list #'(body ...))) >>>>>>> (reverse acc))])) >>>>>>> >>>>>>> ($list 1 >>>>>>> (define x 2) >>>>>>> x) >>>>>>> >>>>>>> There are problems though. If I change define to define2 as follows: >>>>>>> >>>>>>> (define-syntax-rule (define2 x y) >>>>>>> (define-values (x) y)) >>>>>>> >>>>>>> ($list 1 >>>>>>> (define2 x 2) >>>>>>> x) >>>>>>> >>>>>>> Then I get the “identifier used out of context” error. This doesn’t >>>>>>> make sense to me at all. My define2 should be very similar to define >>>>>>> … >>>>>>> >>>>>>> There’s also another weird problem: >>>>>>> >>>>>>> ($list 1 >>>>>>> (define-syntax (x stx) #'2) >>>>>>> x) >>>>>>> >>>>>>> The above works perfectly, but by wrapping x with #%expression, I >>>>>>> get the “identifier used out of context” error again. >>>>>>> >>>>>>> ($list 1 >>>>>>> (define-syntax (x stx) #'2) >>>>>>> (#%expression x)) >>>>>>> >>>>>>> What did I do wrong? >>>>>>> >>>>>>> Thanks! >>>>>>> >>>>>> -- >>>>> 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 [email protected]. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/racket-users/748eead8-76b9-43bc-94da-2c832ba8896do%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/racket-users/748eead8-76b9-43bc-94da-2c832ba8896do%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> >>>> -- >>> 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 [email protected]. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/racket-users/ae981bda-94d3-43d2-ae23-a41f5160aa0ao%40googlegroups.com >>> <https://groups.google.com/d/msgid/racket-users/ae981bda-94d3-43d2-ae23-a41f5160aa0ao%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > 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 [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/racket-users/30972297-14f6-4cf9-8821-de5753f3dacfo%40googlegroups.com > <https://groups.google.com/d/msgid/racket-users/30972297-14f6-4cf9-8821-de5753f3dacfo%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CADcuegvqrnU9nviOUk3zmy_U1ySNsh0Tni5R%3DYKczodgFArwHw%40mail.gmail.com.

