[Some of these points may have come up earlier, I just didn't want to lose comments so reply as I read it.]
[To be clear in advance, the following should be qualified by an "I love it".] Two days ago, Matthew Flatt wrote: > > Given the term "submodule", the first thing that you're likely to try > will work as expected: > > #lang racket/base > > (module zoo racket/base > (provide tiger) > (define tiger "Tony")) > > (require 'zoo) > > tiger > > Within `module', a module path of the form `(quote id)' refers to > the submodule `id', if any. If there's no such submodule, then > `(quote id)' refers to an interactively declared module, as before. This is *really* nice in how it's building a scope for module names, but OTOH, it makes the quote seem more like a syntactic hack... > [...later...] > > (require (submod 'zoo monkey-house)) > > [...] a shorthand for `(submod "." zoo)' [...] ...especially here -- why is there a quote only on the first and not on the second? Is there any meaning for (submod foo) without the quote (or a sting)? If not, then having (submod zoo monkey-house) seems beter in building up an intuition of `submod' implicitly "quoting" the following name. Perhaps a more obvious question is why aren't all `submod' uses get "." as an implicit first expression? IIUC, this means that it works nicely without quotes, and there's only a single magical ".." thing. > The 'zoo module path above is really a shorthand for `(submod "." > zoo)', where "." means the enclosing module and `zoo' is its > submodule. You could write `(submod "." zoo monkey-house)' in place > of `(submod 'zoo monkey-house)'. I also love the analogy to paths -- but using strings for them doesn't look so nice, since strings are begging to be combined... (I can already see myself wishing for "./../foo".) Other than the obvious reader issue, would there be a problem in using `|.|' and `..' for these (and making them into special module names)? Or if there was always an implicit first ".", then there's only need for a single `..' magic token thing... (It even makes syntactic sense that (submod) is something that you can't require.) Reading the later "Design Issues" section, I see that these are indeed arbitrary. So to clarify, I propose a `submod' form that always begins with a "." (under its current semantics), with no need to use a quote, and with `..' being a special name that goes up the hierarchy. To make things connect nicely to toplevel requires, (submod foo) could also resort to the repl-entered module thing, which means that we now have: (require (submod foo)) is very common, so it can be written a bit more conveniently as (require 'foo) (But this might be pushing the description into showing them as closer than they are.) > Instead of `require'ing its enclosing module, a `module*' form can > use `#f' as its language, in which case its lexical context starts > with all of the bindings of the enclosing module (implicitly > imported) instead of with an empty lexical context. As a result, the > submodule can access bindings of the enclosing module that are not > exported: > > #lang racket/base > > (module aquarium racket/base > (define fish '(1 2)) > > (module* book #f > (append fish '(red blue)))) > > (require (submod 'aquarium book)) The explanation for this looks reasonable, but the result looks unfortunate since the common case requires you to remember to add two special things (the `*' and `#f'). But I also really don't like to abuse `module' for both uses. How about just (submodule foo ...) be a more memorable syntax for (module* foo #f ...)? Later, I see: > As things stand, the ugly pattern `(module* main #f ...)' would be > common. Probably we should have a macro that expands to `(module* main > #f ...)'. Should the macro be called `main'? So above is my suggestion. But maybe even make it more generally convenient so it can cover the `test' use without needing a library -- taking what Jay did (I think, didn't look at the code or the followups, yet), and making this: (submodule <name> E ...) be something that can appear anywhere in the code, expands to what (module* main #f E ...) is doing now, *and* is allowed to be used more than once, with all uses being collected into a single submodule. This way I can easily interleave regular code, main code, test code, sanity assertion code, documentation code etc. IOW, I see this as something that can be used straightforwardly with any testing tool, or made into a macro by one, or being used in the obvious way by in-line documentation tools like Neil V's mcfly thing (which is more straightforward for this than srcdoc). > A common use of `module*' is likely to be with `main', since > `racket' will load a `main' submodule (after `require'ing its > enclosing module) for a module named on its command line. For > example, if you run this program via `racket': > > #lang racket/base > > (provide fish) > (define fish '(1 2)) (Just in case this was missed and is/will be in some docs: that should probably have been '(2 1).) > The `#lang' reader form was previously defined as a shorthand for > `#reader' where the name after the `#lang' is mangled by adding > "/lang/reader". With submodules, `#lang' first tries using the name > as-is and checking for a `reader' submodule; if it is found, then > the submodule is used instead of mangling the name with > "/lang/reader", otherwise it falls back to the old behavior. (BTW, there's an obvious question here of why not do that for all paths, so that `foo/bar/baz' can access a `bar/baz' submodule in `foo' or a `baz' in `foo/bar'... This is very similar to what I did in the old plt-schme.org web page sources, where a page is usually a file, but some files have subpages (with a `begin-page'). It was a mess.) > #lang racket/base > > (provide (all-from-out racket/base) > fish) > (define fish '(1 2 3)) > > (module reader syntax/module-reader > #:language 'ocean) [This could be even nicer with: (module reader syntax/module-reader #:language (submod ".")) ] -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! _________________________ Racket Developers list: http://lists.racket-lang.org/dev