[R6RS] modules?

R. Kent Dybvig dyb
Tue Apr 13 10:49:19 EDT 2004


After reviewing Matthew's brief note, the module documentation page he
refers to, and a bit of the DrScheme/MzScheme documentation, I've come to
the preliminary conclusion that there are few enough differences between
the MzScheme and Chez Scheme (actually syntax-case) module systems that
we should be able to come up with an appropriate merger of the two.

Here is a brief comparison.  I'm not sure it's 100% accurate, since I
do not yet fully understand the MzScheme module system.

Similarties:

  * Both control visibility of identifiers

  * Both allow export of syntax

  * Top-level module relationships in both are acyclic

Differences:

  * Syntax-case (SC) supports internal modules (anywhere definitions
    are allowed), MzScheme (MS) only top-level modules.  Internal
    modules can be mutually recursive, so one can, e.g., split a program
    into mutually recursive modules and treat them as one compilation
    unit via a "main" file with the following structure.

        (let ()
          (include "file1") ; defines modules 1a, 1b, ...
          (include "file2") ; defines modules 2a, 2b, ...
          ...)

  * SC supports module imports (requires) anywhere definitions are
    allowed, including internally and at top level; MS allows requires
    (imports) only within a (top-level) module form.

  * MS has a "require-for-syntax" form that makes module bindings
    available for macro implementations at expand time; SC does not
    but doesn't need it since one can always stick an import right
    in the body of the macro implementation, e.g.,

        (define-syntax a
          (lambda (x)
            (import goodstuff)
            <expansion code>))

  * MS evaluates the module definitions and expressions by need;
    SC evaluates the module definitions and expressions eagerly.

  * MS forces the programmer to specify the language in which a module
    is implemented (the initial require/import), as in:

        (module name language <stuff> (provides <export> ...))

    SC provides a default language at top level (call it "scheme");
    modules anywhere are scoped (can see bindings in the context of)
    where they appear.  SC allows one to restrict this down to a
    particular language with import-only.  So the following in SC is
    roughly equivalent to the above in MS:

        (module name (<export> ...) (import-only language) <stuff>)

    The module keyword itself is a normal identifier bound in the
    "scheme" module.

  * MS has some nice syntax for specifying exports and such, like
    (provides (all-from M)) to reexport the exports of M.  These can
    be written at the source level in SC but they are not built in.

  * MS builds in a notion of file loading/searching.  SC lacks this
    feature.

  * MS creates a different set of bindings for each expansion phase.
    SC does not.

There are also some superficial syntactic similarities and differences.

A brief glance at this list shows more differences than similarities,
but most of the differences aren't fundamental, and a merger of the
two systems should be feasible.  Here is my ideal merger:

  * Adopt the common features of both systems.

  * Adopt SC internal modules and top-level/internal imports.

  * Adopt SC notion of modules being scoped where they are defined
    plus import-only, or MS notion of language being specified with
    a way to allow the language to default to the current scope.

  * Adopt MS syntax for specifying exports and such.

  * Adopt MS file loading/searching.

I could go either way on when module definitions and expressions are
evaluated, although I'm concerned that by need evaluation gets us into
some of the same problems that we have with delay/force.  I understand
neither the semantics nor benefits of MS's different bindings for
different phases, so I don't yet have an opinion on that.

Kent


More information about the R6RS mailing list