> I am writing the chapters of my Adventures relative to the > R6RS module system and to the phase separation concept. In > doing so, I realized that I am still missing a crucial > point. Therefore, I am asking for enlightenment here. > > As I understand, there are three possible semantics for R6RS > implementations (I may be using incorrect terminology, but > it should be clear what I mean):
Here, you're talking about the visibility/scope/meaning of identifiers (those that are imported and those that are defined with define/define-syntax). The term "phase separation" is ambiguous as it pertains to other issues like when, why, and how many times libraries are expanded/invoked. > 1. full phase separation (mzscheme, Larceny); there is an > infinite tower of metalevels, and you are forced to specify > at which phase you want to import the names; The number of meta levels is always bounded by the number of things you type in the import-for clause. It's always finite in the mzscheme/larceny world. In Ikarus however, imported identifiers are available at all levels. > 2. partial phase separation (Ikarus); importing a name > imports it at all levels; > > 3. no phase separation (REPL of Ikarus and Ypsilon). > > The rationale for 1 is that some people (not me) want the > freedom to use different languages at different levels. The rationale for 1 is in Matthew Flatt's "Composable and Compilable Macros" paper. I don't recall there is any mention of "different languages at different levels" in that paper. The main rationale that I get is to control side effects that happen at compile time (see the zoo examples). > The rationale for 2 is that it is much easier and programmer > friendly; it also avoids the potentially infinite > duplication of namespaces, one per level. It also happens to be easier to implement. (I've implemented the mzscheme model before coming up with the new stuff.) > The rational for 3 is that at the REPL it is very convenient > to define a helper function and then use it directly in a > macro defined later on. This is not the reason as far as Ikarus is concerned. More below. > The point I am missing: why do not keep the semantics of the > REPL even for scripts and libraries? I mean in Ikarus. > Clearly people wanting full phase separation have no > interest in this: actually they force you to import > explicitly even auxiliary macros, not only auxiliary > functions. Ikarus instead does not force you to put > auxiliary macros in a separate module. It does not force you to put auxiliary macros in separate libraries because there is no reason for it. More below. > Thinking is the same direction, it is clear that the > compiler in theory has access to the helper functions > defined before the macros they are intended to be used to, > and it could make use of this knowledge. Nop! The compiler does NOT have access to helper functions defined in the same compilation unit until the entire unit is expanded. Consider a library containing: (define t (make-table ---)) (define-syntax m (lambda (x) --- use t ---)) (initialize-table! t) At the time the code for m is expanded, the expander has not yet finished expanding the library, and has no knowledge of the initialization code. If we allow the use of t, we'd be hosed for using an uninitialized table. > Instead, R6RS-compatibility forces us to put the auxiliary > functions in an auxiliary module and to import them. No. What forces us is the desire to be able to fully expand and compile each library without having to also evaluate it. We can relax this at the REPL since every expression entered is expanded and evaluated anyways and thus can be used in subsequent variable and syntax definitions. The same is not true for libraries. > I want to understand if you (Aziz and more generally the > people here which I believe are no fan of full phase > separation) think that the restriction from the R6RS is > wrong and no phase separation at all would be a better > solution, or if I am just missing something and perhaps the > partial phase separation of splitting macros from auxiliary > functions (and in general other names that would be define > at runtime only) is needed in some way. I mean, I would like > to go in a direction of no phase separation at all, where > all names at toplevel are defined both at compile time and > at runtime. This was the semantic I expected from day one > when I learned Scheme, and it is the semantic of the REPL. Although I too am not a fan of having to define auxiliary functions in separate libraries, there's really no way around it. Such functions have to be defined in such way that they be fully expandable and their dependencies met before they are used. Having them in separate R6RS libraries is one way of achieving that. Please let me know if any of the above is not clear. Aziz,,,
