[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: module questions



Quoting Michael Vanier:
> Currently, units are a library extension;
> are they going to be maintained in the future?

Absolutely.

> Or is the module system
> going to expand to take over their functionality entirely?

Never.

See below for a longer answer, excerpted from 
  http://www.htus.org/Book/Staging/how-to-use-modules/

> Also, it occurred to me after posting that a much simpler way to achieve my
> goals is simply to use "load" to bring together files with mutual
> dependencies into a third file, which could itself be a module.

Eli pointed out that you want `include'. I'd like to emphasize that, as
a rule of thumb,

         -----------------------------------------
         a modulized program will never use `load'.
         -----------------------------------------

The `load' procedure works in the top-level environment, and none of
the bindings in the top-level environment are visible within a module
(except though functions that explicitly consult the top-level
environment, such as `load'). Getting rid of `load' was a specific
design goal; `load' interferes with compilation, analysis, and even
Check Syntax.

> Interestingly, python
> seems to handle mutually recursive intermodule references without any
> problem.  What is the reason for the prohibition on cyclic module
> dependencies in mzscheme?

With Python, you get one language for the body of modules --- no
macros, and certainly no macro whose expansion produces a `provide'
declaration.

To expand/compile a module M, MzScheme must determine syntax that is
imported into M. Getting imported syntax, in turn, requires first
expanding each module that M imports. If an imported N itself imports
from M, then expansion gets stuck; even if we think in terms of
"partial expansion", a minimally useful expansion of N will need to
know the syntax exports from M, which we can't know until we get the
syntax imports from N, ...

A way around this problem would be a `require' form that gets only
non-syntax from some module, and where all imported names are listed
explicitly. In that case, it would not be necessary to consult the
imported module at all (until invocation time, to check that the named
variables are really exported).

But for now, as we explore the balance between modules and units (just
as we continue to explore the balance between functions and objects),
leaving mutual recursion to units seems best.

Matthew

----------------------------------------

>From Modules to Components

The `module' form is for namespace management. It constrains the scope of
definitions, and it declares explicitly the constructs and bindings
used to implement a module's code.

The `module' form does not support abstractions over a set of
definitions, at least not directly. For example, although the face2
module's implementation is independent of the implementation details of
new-canvas and draw-rect!, face2 nevertheless works only with the
implementation that originates from the `canvas' and `shapes' modules
specifically.

To define a face component that can be linked to any canvas
implementation, we can use the `unit/sig' form, which is defined by
"unitsig.ss" in the "mzlib" collection:

[...]

Unlike modules, units can have mutual dependencies: A@ can import from
B@, while unit B@ simultaneously imports from A@. So, another potential
reason to use `unit/sig' (in addition to `module') is to implement
separate program fragments that have mutual dependendencies.

Although `module' and `unit/sig' organize code at roughly the same
granularity, the features needed in a namespace management system are
quite different from those needed in a component system. More
generally, `module' provides an expansion and compilation foundation on
which new programming constructs can be built, including constructs for
implementing components.