2 Module Managers: Module

# 2 Module Managers: `Module`

Module managers grant access to modules identified by urls. Examples and more information on module managers can be found in ``Application Programming''.

## 2.1 Basics

A module manager maintains a module table, that maps urls to modules. To be more precise, the table maps a url to a module or to a future for a module (this is explained later).

A module manager supports the following operations:

link

  Linking takes a url U as input and returns a module M or a future F for a module.

  We say that M or F is linked from U. Most of the time we will not distinguish between M and F.

  Depending on whether the module table already contains an entry for M, the following happens:

  1. If the module table already contains an entry M for the url U, linking just returns M.

  2. If no entry for U is available, a new future F is created and stored under U in the module table. F is returned.

     As soon as the value for the future F is requested, a new thread is created that installs a module from the url U. This is called dynamic linking or linking on demand.

     If under the url U a pickled functor is stored, the module is computed by first loading the functor G. Then G is applied with respect to the url U (this is explained later) which yields a module to which the future F is bound. This also explains why it is okay to not make a distinction between module and future for a module, since the distinction does not has any consequences as it comes to module access.

     If the url U refers to a system module (see also Chapter 3 of ``Application Programming'') the system module is returned.

     The url U can also refer to a native functor, this is described in detail in Part VI of ``Application Programming''.

apply

  Application takes a functor F and a base url U and returns a module M.

  First the import urls of F are resolved with respect to the base url U. Then the resolved urls are used for linking. The returned modules are called argument modules. Then the body of the functor is applied to the argument modules.

enter

  Entering takes a url U and a module M as input.

  The module M is added to the module table under U. If the module table already contains an entry for U, an exception is raised.

A module manager is implemented as an instance of the class `Module.manager`. The class provides methods to link and apply functors and to enter modules into the module manager's module table.

## 2.2 Module Names and URLs

As has been explained above, each module is refered to by a url U, some of which are Oz specific in that they refer to system modules. We just say that the module has the url U.

A module name is a shortcut for a module url. The mapping of module names to full urls is explained in detail in Chapter 3 of ``Application Programming''.

## 2.3 The Class `Module.manager`

Module managers are created as instances of the class `Module.manager`. For predefined abstractions that are build on top of module managers see Section 2.4.

`init`

  > > `init()`

  Initializes the module manager.

`link`

  > > `link(url:``+UrlV``` `ModuleR``<= _)`

  > > `link(name:``+NameV``` `ModuleR``<= _)`

  Links the module identified either by a url `UrlV` (a virtual string) or a module name `NameV` (a virtual string). Returns the module `ModuleR` (which might be a future to a module).

  The argument for the module is optional, if it is omitted the module is requested immediately.

`apply`

  > > `apply(``+Functor``` `ModuleR``<= _)`

  > > `apply(url:``+UrlV``` `+Functor``` `ModuleR``<= _)`

  > > `apply(name:``+NameV``` `+Functor``` `ModuleR``<= _)`

  Applies the functor `Functor`, where the url `UrlV` (a virtual string) or the module name `NameV` (a virtual string) serve as base url for linking the functor's import. If neither a module name nor a url is given, the current working directory is taken as base url.

  The argument for the module is optional.

  Please note that the resulting module is not added to the module table, the URL argument only serves as base url for the functor's import.

`enter`

  > > `enter(url:``+UrlV``` `ModuleR``)`

  > > `enter(name:``+NameV``` `ModuleR``)`

  Installs the module `ModuleR` under the url `UrlV` (a virtual string) or the module name `NameV` (a virtual string).

  Raises an exception if the module manager already has a module under that particular url installed.

## 2.4 Predefined Abstractions

`link`

  > > `{Module.link` `+UrlVs``` `Rs``}`

  Takes a list `UrlVs` of urls (as virtual strings) and and returns the list of modules created by linking.

  All functors are linked by the same module manager, however each application of `Module.link` employs a new module manager. This has the following consequences:

  - Modules imported by several functors are shared.

  - Each application of `Module.link` links required functors anew. That is, after replacing a functor on the file system, an application of `Module.link` considers the new functor for linking.

  `Module.link` is defined as follows:

  > `fun {Module.link UrlVs}
  > ModMan = {New Module.manager init}
  > in
  > {Map UrlVs fun {$ Url}
  > {ModMan link(url:Url $)}
  > end}
  > end`

`apply`

  > > `{Module.apply` `+Xs``` `Rs``}`

  Takes a list of functors or pairs of urls (as virtual strings) as input. The url in a pair of url and functor describes the base url with which the import urls of the functor gets resolved. If it is missing the current working directory is used for url resolution.

  Returns a list of modules computed by functor application.

  `Module.apply` is defined as follows:

  > `fun {Module.apply UFs}
  > ModMan = {New Module.manager init}
  > in
  > {Map UFs fun {$ UF}
  > case UF of U#F then
  > {ModMan apply(url:U F $)}
  > else
  > {ModMan apply(UF $)}
  > end
  > end}
  > end`