Apologies to mobile users. The superscripts added by +scopes aren't boxes in the Web client.
To clarify my question: how do I handle the situation where variables bound by one macro and used by another are out of scope when file boundaries are involved? The +scopes into shows that the scope sets go from intersecting to disjoint or sharing only a macro scope. On Mon, Jun 3, 2019, 11:52 AM Eric Griffis <ded...@gmail.com> wrote: > Several times now, I've run into one or another form of the following > problem: > > Say I want to build primitives to > > 1. declare an "interface" as a list of names, and > 2. implement and use those names at run time in a limited scope > > Concretely, I want to run the following code: > > (interface Speaker say speak) > (implement Speaker displayln (say 'hello) speak) > > If I put these lines at the end of a file that implements the two forms, > it should (displayln 'hello) when I run it. > > Here is the interface macro: > > (define-syntax (interface stx) > (syntax-case stx () > [(_ id member-id ...) #'(define-syntax id #'(member-id ...))])) > > The implement macro is trickier. A naive implementation looks like this: > > (define-syntax (implement stx) > (syntax-case stx () > [(_ class-id def ... expr) > (with-syntax ([(id ...) (syntax-e (syntax-local-value #'class-id))]) > #'(letrec ([id def] ...) expr))])) > > It fails with the following message: > > ; /tmp/j.rkt:44:30: say: unbound identifier; in: say; context...:; > #(570423 use-site) [common scopes]; other binding...:; local; > #(570422 macro) [common scopes]; common scopes...:; #(570223 module) > #(570226 module j) #(570426 local) #(570427 intdef); #(570428 local) > > Incorporating the debug-scopes package's +scopes macro shows this: > > (letrec⁰˙˙¹ > ((say⁰˙˙¹ displayln⁰˙˙³) (speak⁰˙˙¹ (say⁰˙˙³ (quote⁰˙˙³ hello⁰˙˙³)))) > speak⁰˙˙³)ˢˡⁱ⁼²⁺ᵘˢᵉ⁼³0 module 5705121 module j 5705152 macro 5707193 > use-site 570720 > > For reasons I don't yet fully comprehend, it just works out if I use > syntax-local-introduce on the id's, so +scopes gives me this: > > (letrec⁰˙˙¹ > ((say⁰˙˙³ displayln⁰˙˙³) (speak⁰˙˙³ (say⁰˙˙³ (quote⁰˙˙³ hello⁰˙˙³)))) > speak⁰˙˙³)ˢˡⁱ⁼²⁺ᵘˢᵉ⁼³0 module 5712471 module j 5712502 macro 5714553 > use-site 571456 > > But if the interface and implement invocations are not in the same file > as their implementations, it breaks with a similar error: > > ; /tmp/h.rkt:5:30: say: unbound identifier; in: say; context...:; > #(572682 module) [common scopes]; other binding...:; local; #(572388 > module) #(572391 module j) #(572596 module); #(572599 module j) [common > scopes]; common scopes...:; #(572685 module h) #(572700 local) #(572701 > intdef) #(572702 local) > > In this situation, +scopes gives: > > (letrec⁰˙˙³ > ((say⁴˙˙⁵ displayln⁴˙˙⁶) (speak⁴˙˙⁵ (say⁴˙˙⁶ (quote⁴˙˙⁶ hello⁴˙˙⁶)))) > speak⁴˙˙⁶)ˢˡⁱ⁼⁶⁺ᵘˢᵉ⁼0 module 5768541 module j 5768572 module 5770563 > module j 5770594 module 5771505 module h 5771536 macro 577173 > > If I move the interface invocation back into the original file and keep > the implement invocation in a separate file, I get the same error but > +scopes gives something slightly different: > > (letrec⁰˙˙³ > ((say⁰˙˙⁴ displayln⁴˙˙⁶) (speak⁰˙˙⁴ (say⁴˙˙⁶ (quote⁴˙˙⁶ hello⁴˙˙⁶)))) > speak⁴˙˙⁶)ˢˡⁱ⁼⁴⁺ᵘˢᵉ⁼0 module 5723881 module j 5723912 module 5725963 > module j 5725994 macro 5726975 module 5726826 module h 572685 > > What's going on here? How do I fix this? > > Eric > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CAORuSUzCs5SiisiLjG3uQMiBdK%2BOHOjq8sgEsNdw54LUMAeEEA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.