On Tue, Feb 1, 2011 at 3:09 PM, Matthew Flatt <[email protected]> wrote: > At Sat, 29 Jan 2011 15:07:37 -0500, Carl Eastlund wrote: >> The following program binds => at both phase 0 (module-scoped macro) >> and phase 1 (lexically-scoped value). The use of the => macro at the >> end expands into a recursive reference to =>, which in turn produces >> the error "compile: identifier used out of context". As I understand >> it, this happens because the identifier => has been taken out of the >> scope of its phase 1 binding. However, it is being used here at phase >> 0. I would much prefer if the expander simply ignored the phase 1 >> binding and carried out the recursive macro invocation. >> >> Before I file this as a bug report, have I understood what's going on? >> Is there any reason this shouldn't or couldn't be fixed? > > It would indeed be sensible to have local bindings at phase N shadow > only at phase N, leaving bindings in other phases as they are. > > We haven't done that so far for two reasons: > > * They're local bindings, so you can always pick different identifiers > for bindings that have overlapping scopes. > > * If you use the same identifier for bindings with overlapping scopes > at different phases, the results can be confusing. > > As an example of the latter, consider > > (syntax-case stx () > [(_ id) > (let ([id (munge #'id)]) > #'(list id))]) > > versus > > (syntax-case stx () > [(_ id) > (with-syntax ([id (munge #'id)]) > #'(list id))]) > > Currently, only the latter is sensible, and the former leads to a phase > error. If the two `id's were bound only in their respective phases > (i.e., 0 and -1), then the former example's result template would use > `id' from the pattern, quietly ignoring the `let' binding. > > I don't think that's a great example, but it has the flavor of a kind > of mistake that I make. Given the options, I think I prefer to rename > local variables that collide to trigger errors, instead of having > bindings that look like they shadow lead to something different > (usually quietly). But I haven't actually tried programming with the > other option. > > Of course, with respect to the possibility of confusion, it's just as > potentially confusing to use the same identifier for imported bindings > different phases. For example, it can be confusing that `lambda' is > available at multiple phases, perhaps even with different meanings. In > contrast to just local bindings, however, picking different names for > all bindings in different phases --- including alternatives for > `lambda' at different phases --- would be truly inconvenient.
Thanks for the response, Matthew. I wound up concluding I was better off using different names anyway, so I think the status quo is okay. However, the error message could be more informative. For instance: "compile: reference to <name> in phase <i> is out of the scope of <name> defined in phase <j> at <srcloc>; bindings in all phases must be in scope." --Carl _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev

