A module can be imported more than once. If the module is shared, then there will only be a single instance of the imported module, and the code and the data that it defines will be shared by all of the importers. If the module is not shared, then each time it is imported, a separate instance of the code and the data will be created.
Both techniques have their uses:
floattype, you'll probably want all users of the type to use the same type—so that its values can be interchanged.
The sharing/non-sharing distinction is determined by a module definition, not by its importers. You specify that a module is shared by following the keyword
module at its head by
shared as and a name, as in:
module shared as com.stilo.math.float ; The rest of the floating point math. module. ; Shared because it has no local state, and ; because the "float" type needs to be common to all uses.
When a module is
shared, the following apply:
sharedmodule is used by the compiler. All other
imports of modules with the same "shared as" name use the same compiled module, even if their source code is different from the first one.
opaquetype is exported by a
sharedmodule, all its importers get the same type.
opaquetypes exported from non-shared modules produce a distinct type for each
process-startrules of a
sharedmodule are run as though they were declared where it is first imported. The
process-endrules of a
sharedmodule are run as though they were declared where it is last imported (even though those
process-endrules are taken from where the module is first imported). This ordering of things helps ensure that modules are initialized early enough, but not shut down too early.
sharedmodule isn't allowed to
requireanything. Because an instance of a
sharedmodule can be imported from more than one location, if it
required anything, it would have to take what's supplied to it from one of its importers, and ignore what's supplied by other importations, and that would result in ambiguity and unexpected behavior.