# 3 Module Managers

So far we only dicussed how functor definitions can be developed in a modular fashion. This chapter explains how modular applications are executed.

The chapter is kept informal, a more detailed explanation of module managers and how module managers link applications can be found in [DKSS98].

## 3.1 Overview

A module manager maintains a module table. The module table maps urls (or to be more precise, full module urls) to modules or futures to modules.

A module manager links a module at url U as follows:

1. If U is already in the module table, the module manager returns the entry in the module table.

2. If U is not yet in the module table, the module manager creates a new future M and stores M under key U in the module table. As soon as the value of future M gets requested, the module manager installs a module from the url U.

Linking is done lazily: only when the value of the module is requested (usually implicitly, when the application attempts to access an exported feature), the module gets installed. A module with full module url U is installed as follows, where the installation procedure returns a module M:

1. The pickled functor stored at U is loaded.

2. The module manager computes the full module urls for its imports. This step is detailed in Section 3.3 and Section 3.4.

3. It recursively links all functors with the full module urls computed before. This yields the argument modules.

4. It applies the functor body to the argument modules, which returns the module M.

## 3.2 Lazy Linking

In the above section we have discussed that modules are subject to lazy linking: Only when a module is requested, the functor to compute that module gets loaded.

Lazy linking has dramatic effect on the startup time of an application: applications can start small in a fraction of a second and load additional functionality on demand. And all this happens completely transparently.

System modules are also subject to dynamic linking. Even though module managers give the impression that the system modules are always there, they are also loaded on demand. An application that takes good advantage of that fact is for example the Oz Programming Interface which starts quickly even though it imports all system modules.

## 3.3 Import Specifications

The entire import part of a functor is called the import specification. Each import specification consists of several import clauses. Each import clause consists of a mandatory module name and an optional module url that must be preceded by the `at` keyword.

For example, in the import specification

> `import
> DB
> MyForm at 'Form.ozf'`

the first import clause is `DB` which just consists of the module name `DB` and does not provide a module url. The second import clause is `MyForm at 'Form.ozf'` which consists of the module name `MyForm` and the module url `'Form.ozf'`.

The first step in linking a functor is that the module manager computes for each import clause the full module url. This is done according to the following rules:

1. If the import clause features a module url U, the full module name is U.

2. If the import clause consists of a module name M only, where M is the name of a system module, the full url is `x-oz://system/`M, that is the module name prefixed by `x-oz://system/`.

3. If the import clause consists of a module name M only and M is not the name of system module, the full url is M`.ozf`, that is the module name suffixed by `.ozf`.

All currently defined system modules are listed in Table 3.1.

Name | Description | Documentation
--- | --- | ---
Application Programming
`Application` | Command processing and application termination | Chapter 1 of ``System Modules''
`Module` | Module managers | Chapter 2 of ``System Modules''
Constraint Programming
`Search` | Search engines | Chapter 4 of ``System Modules''
`FD` | Finite domain propagators and distributors | Chapter 5 of ``System Modules''
`Schedule` | Scheduling propagators and distributors | Chapter 6 of ``System Modules''
`FS` | Finite set propagators and distributors | Chapter 7 of ``System Modules''
`RecordC` | Feature constraints (record constraints with open arities) | Chapter 8 of ``System Modules''
`Combinator` | Deep-guard combinators | Chapter 9 of ``System Modules''
`Space` | First-class computation spaces | Chapter 10 of ``System Modules''
Distributed Programming
`Connection` | Connecting to running Oz processes | Chapter 11 of ``System Modules''
`Remote` | Remote module managers | Chapter 12 of ``System Modules''
`URL` | URL parsing and resolution routines | Chapter 13 of ``System Modules''
`Resolve` | URL resolving | Chapter 14 of ``System Modules''
`Fault` | Handling faults in distributed programs | Chapter 15 of ``System Modules''
Open Programming
`Open` | Support for files, sockets, and pipes | Chapter 19 of ``System Modules''
`OS` | POSIX compliant operating system support | Chapter 20 of ``System Modules''
System Programming
`Pickle` | Saving and loading of persistant values | Chapter 21 of ``System Modules''
`Property` | Querying and configuring engine properties | Chapter 22 of ``System Modules''
`Error` | Error handling routines | Chapter 23 of ``System Modules''
`Finalize` | Automatic garbage collection for native entities | Chapter 25 of ``System Modules''
`System` | Miscellaneous system related procedures (printing) | Chapter 26 of ``System Modules''
Window Programming
`Tk` | Classes and procedures for window programming | Chapter 27 of ``System Modules''
`TkTools` | Predefined abstractions to handle menus, dialogs, and so on | Chapter 28 of ``System Modules''
Graphical Tools
`Browser` | Incremental display of Oz values | ``The Oz Browser''
`Panel` | Monitor and configure the running engine | ``Oz Panel''
`Explorer` | Visual constraint programming tool | ``Oz Explorer - Visual Constraint Programming Support''
`Ozcar` | Interactive debugger | ``The Mozart Debugger''
`Profiler` | Profiling of Oz programs | ``The Mozart Profiler''
Miscellaneous
`ObjectSupport` | Generic classes for object oriented applications | Chapter 29 of ``System Modules''

Table 3.1: System modules.

## 3.4 Url Resolution

Given the full url names for each import clause, the module manager determines the urls from which functors are to be loaded by url resolution. Url resolution takes two urls (one is called the base url and the other is called the local url) as input and computes a new resolved url. The process of url resolution you already know from organizing your html-pages: a url for a relative href-link is resolved with respect to the base url of the containing document.

In this respect, a module manager will behave similarly to a web-browser. When it installs a module that was loaded from url U, the latter's full import urls are resolved with respect to U. Figure 3.1 shows a small example, where the root functor has the absolute filename `/home/schulte/A.ozf`.

Name | Resolved url | Import specification
--- | --- | ---

`A`

`/home/schulte/A.ozf`

> `import
> B at 'down/B.ozf'
> C at 'http://www.foo.org/C.ozf'`

`B` | `/home/schulte/down/B.ozf` | empty

`C`

`http://www.foo.org/C.ozf`

> `import D at 'D.ozf'`

`D` | `http://www.foo.org/D.ozf` | empty

Figure 3.1: Example for resolving urls.

## 3.5 User-defined Module Managers

When the engine starts it has the root module manager that executes the root functor and subsequently links imported functors. However, in many cases it is desirable that applications can create private module managers that just link particular functors.

As an example, suppose we want to use more than a single data base as implemented by the functor `DB.ozf` as shown in Section 2.3

In the Oz Programming Interface, we can link `DB.ozf` twice with two new and different module managers as follows:

> `[DBA]={Module.link ['DB.ozf']}
> [DBB]={Module.link ['DB.ozf']}`

Both `DBA` and `DBB` refer to two independent data bases.

You can observe lazy linking easily. Browsing `DBA` as follows

> `{Browse DBA}`

shows `DBA<Future>`, which means that `DBA` still refers to a future. Requesting the module by, for example, adding an entry to the data base is also reflected in the Browser: the display of `DBA<Future>` is replaced by a representation of the module's value.

That both module managers work independently can be verified by browsing `DBB`.

`Module.link` takes a list of urls, creates a new module manager and maps each url U to the module created by linking the functor at U. Reference documentation can be found in Chapter 2 of ``System Modules''.

## 3.6 Functors in the Oz Programming Environment

Functors are first class entities in the language that can of course also be created in the Oz Programming Interface. This eases development of functors considerably.

Suppose the following demo functor definition

> `declare
> functor F
> export Pam
> define
> fun {DoPam Xs P Ys}
> case Xs of nil then Ys
> [] X|Xr then {DoPam Xr P {P X}|Ys}
> end
> end
> fun {Pam Xs P}
> {DoPam Xs P nil}
> end
> end`

After feeding the definition, the defined functor can be applied as follows:

> `[M]={Module.apply [F]}`

The module `M` can be used in the OPI as usual, that is

> `{Browse {M.pam [1 2 3] fun {$ I} I+1 end}}`

displays the list `[4 3 2]`.

`Module.apply` takes a list of functors as argument, creates a new module manager, applies each functor element and returns the resulting list of modules. It is also possible to specify the base url used in linking the argument modules of the applied functor. For more information see Chapter 2 of ``System Modules''.

Of course, also other situations allow to take advantage of first-class functors and that they can be applied by module managers. In particular they are useful for remote module managers that create new Oz processes on networked computers. You can learn more on this issue in ``Distributed Programming in Mozart - A Tutorial Introduction''.