In discussions with some people at (seventh RacketCon), I managed to solve a few open problems I had in my implementation of Hackett. One thing I didn’t get a good answer for, however, is implementing a language with multiple namespaces. Hackett is not dependently-typed, so it is pointless and inconvenient for types and values to share the same namespace; indeed, it is often useful and idiomatic in Haskell to reuse names for both type variables and runtime variables.
Racket is, of course, a staunch Lisp-1, and it has a single namespace. I generally think this is the right default, but for Hackett, I’ve already run into situations in which I would strongly prefer the types and value namespaces remain separate. Fortunately, Racket often makes it possible to build these things as derived concepts, so I am hopeful I will be able to implement this without too much pain. I currently have an understanding of two possible approaches for implementing multiple namespaces. The first appears to be the usual technique of maintaining a separate binding table (using free id tables from syntax/id-table). This is often good enough, but it isn’t good enough for Hackett, since Hackett needs to support arbitrary local bindings and bindings that can be tracked and renamed separately from the Racket binding they are “attached” to. An alternative approach that I have considered (and discussed briefly with some people) is to introduce a “value” scope using make-syntax-introducer in #%module-begin, then use a separate “type” scope when parsing types to keep the two bindings completely separate. This seems more promising, but it has problems of its own. Specifically, the main question occurs when considering code that spans more than a single module. What do require and provide do? For the provide case, it doesn’t seem too hard to have a (type-out ....) provide transformer, but what happens when a user requires the module? Since my understanding is that modules essentially only provide a set of *symbols* per phase, not identifiers, would I need to mangle names in order to allow a module to export a type with the same name as a value? Would I need to write my own version of require to handle this without wrapping all imports in a require transformer? What about interop with other Racket languages? This seems like a significant burden to put on me as the author of a language, but I don’t know of a better way. Is there prior art here? Is there a simpler solution? And are there any pitfalls I haven’t yet considered? Thanks, 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. For more options, visit https://groups.google.com/d/optout.