As Alexis notes, getting the arrows right in general is tricky. But `block` is also currently buggy in that it does not expand to `#%expression` when not in an expression context. (`block` is buggy in at least one other way as well, but that needs a deeper fix: https://github.com/racket/racket/issues/3198)
On Sunday, June 7, 2020 at 4:45:34 PM UTC-6, Sorawee Porncharoenwase wrote: > > Wow, so block is currently buggy?! > > On Sun, Jun 7, 2020 at 3:31 PM Michael Ballantyne <[email protected] > <javascript:>> 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] <javascript:>. >> 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/f183fa2c-8ff0-4f26-9aae-fe5acb19ba79o%40googlegroups.com.

