> On Jun 7, 2020, at 17:44, Sorawee Porncharoenwase <sorawee.pw...@gmail.com> > wrote: > > Wow, so block is currently buggy?! >
This issue isn’t with `block`, per se (though `block` could cooperate more nicely with definition context expansion to avoid this problem). You can reproduce it without any first-class definition contexts at all: #lang racket (define-syntax-rule (m) (displayln 'old)) (let () (m) (define-syntax-rule (m) 'new) (void)) Arguably, the real issue is the mechanism behind Check Syntax. Check Syntax collects information about uses and bindings from the fully-expanded program, but that is not straightforward for macro uses and local macro bindings, since those go away after expansion. So the expander annotates the program with information about disappeared identifier uses and disappeared local bindings using the 'origin, 'disappeared-use, and 'disappeared-binding syntax properties. The hope is that the binding structure of the source program can be reconstructed from the fully-expanded program by inspecting identifiers’ scopes. This seems plausible, since the scopes of a fully-expanded program dictate the binding structure of runtime variables by definition. However, this example reveals a flaw in that logic: resolution of macro bindings also involves a temporal component, since the compile-time binding table evolves as the program is expanded. Frankly, this temporal dependency is unsatisfying. For runtime bindings, we enjoy predictable recursive definition contexts and inter-module lexical binding, courtesy of the module system. But to paraphrase Matthew, resolution of compile-time bindings is “distressingly like the top level,” since it requires interleaving of expansion and evaluation in a similar way. I think this suggests that perhaps there is something fundamentally incomplete in our model of macroexpansion. However, it seems impossible to solve this problem without somehow restricting the macro language: the status quo allows macros to both (a) expand to absolutely anything via arbitrary procedural logic and (b) perform arbitrary side-effects, which allows them to observe expansion order. A more restrictive model could require macros to declare more information up front (which would allow the macroexpander to learn more about the binding structure of a program without fully expanding macros) or could provide access to state through restricted channels in such a way that the expander could “speculatively” expand a macro, then go back later and change its mind. Of course, these would both require radical, deeply incompatible changes to the Racket macro system, so I do not expect them to actually be implemented! But perhaps they can be food for thought. Alexis -- 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/D48BCCBB-AE1F-47CC-93E8-B90D1129E169%40gmail.com.