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/CAORuSUz_v5jYSFQetnuLb6haNx8Hwo0CqR0Bm-jCJO0DT7Bz6w%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.