[R6RS] Re: strawman module syntax
R. Kent Dybvig
Fri Jul 9 15:28:53 EDT 2004
Thank you for the clarifications. Unfortunately, I strongly dislike
several aspects of the proposed design. One of Scheme's charms is that
3 is a program, and not just in the interactive environment. There's no
barrier to entry, no boilerplate stuff to stick on the top of or wrap
around each file. As long as I stay within the base language, I can
just start programming, and do so portably. Another charm is that
there are no reserved words: I can redefine anything I want. Another
is that macros can be used to specialize or generalize any language
construct---including, in Chez Scheme at least, module and import forms.
Another is that one can textually embed programs within other programs
to form larger programs, if some care is taken in the design of the
constituent parts. The proposed design changes all of this because it
includes unnecessary restrictions with its useful new functionality.
The lack of such restrictions has helped make Scheme a good language,
and I see no reason to add them now.
Here are my suggestions:
1. Require the top level of any R6RS-conforming implementation to admit
any mix of R6RS definitions and expressions. Allow conforming
implementations to admit implementation-dependent forms, but require
conforming programs to avoid implementation-dependent forms.
This would address several of the above concerns without hampering
anyone's ability to write exactly the code the original proposal
2. Treat both module and require (import) forms as definitions and
allow them to appear anywhere where other definitions can appear.
As with top-level definitions, top-level module forms may allow one
to do things that don't make sense for internal module forms. I
see no harm in this. Experience has shown that disallowing
internal define-syntax was a bad idea; let's not repeat the mistake
This addresses more of the above concerns, again without hampering
anyone's ability to do what the original proposal allows.
It also permits one to create extended (or restricted) versions of
the module and require forms. This in turn relieves us of some
pressure to satisfy every need in the base syntax for modules.
3. Eliminate the implicit require form from the module syntax, scope
modules where they appear, and introduce a special require form that
blocks off the outside scope, like Chez Scheme's import-only.
This allows us to expand into the (now no-longer implicit) require
form used to specify the language. Again, this is strictly a
generalization of the earlier proposal; in fact, the original module
form can be expressed as a macro.
4. Don't force the use of separate interfaces, i.e., allow one to
require a named module rather than a named interface. Don't support
separate interfaces at all unless we have some portable mechanism
for specifying which of multiple implementations is to used.
There's no point in separate interfaces if only one implementation
is available. We can always generalize the identifier in, e.g.,
(require id), to be an interface rather than a module if we wish to
do so at some later point.
5. If we do support separate interfaces, they should include exported
syntactic abstractions along with any nonexported syntactic
abstractions (and meta definitions, if we support them) into which
exported syntactic abstractions use or expand.
Virtually nothing can be done with code that imports from an interface
without the syntactic abstractions, so there's no point in knowing
the interface before the syntactic abstractions are known.
There are some other things not specified by the proposal that we
need to hammer out, such as whether to include meta definitions or
require-for-syntax, whether to require hidden exports to be named, when
to evaluate module inits, and mutability rules for exported variables.
For the record, I prefer meta definitions and no require-for-syntax,
I prefer to require hidden exports to be named (which we must do anyway
if we ever go the route of separate interfaces), I prefer that module
inits be evaluated once when the module is first loaded, and I prefer
to allow exported variables to be mutated, since control over mutability
seems like an orthogonal issue.
More information about the R6RS