The Avail Programming Language

Module Packages

Large products are typically partitioned into many small units that are arranged into layers of abstraction and encapsulation. When well-applied, this style of organization restricts the visibility of program elements so that it is easy to reason about their spheres of influence. For example, if you know that a method "Internal error:_" is private to a particular module, then you know that it can safely be renamed without having to hunt for references beyond that module; only the module that defined it needs to be searched. Restricting the visibility of program elements makes the task of managing a project with many thousands of data types and operations significantly more tractable.

The private imports section and extended imports section of a module header permit a programmer to fine-tune the visibility of names. This, in turn, allows her to control what messages may be sent by downstream modules. By carefully selecting import specifications across a series of modules, it is possible to tune the visibility of a message to any desired granularity.

It is also possible to tune the visibility of entire modules via a complementary mechanism: module packages. A module package — simply package hereinafter — is a module that contains other modules, called submodules. A package is represented on a file system as a directory whose file name has a .avail extension. Inside the directory there must be a module whose file name exactly matches the name of the enclosing directory. This module is called the module package representative (or just representative).

Consider the following file system structure:

Avail.avail/ Advanced Math.avail/ Advanced Math.avail Combinatorics.avail Data Abstractions.avail/ Foundation.avail/ IO.avail/ Unit Testing.avail/ Avail.avail

This is a high-level snapshot of Avail, the Avail standard library, excerpted for brevity. Each file name that ends with a solidus / (U+002F) is a directory that corresponds to a package; all other file names are regular files that correspond to modules. Only the contents of Avail.avail/ and Advanced Math.avail/ have been expanded. Inside the Avail.avail/ directory is an eponymous file; it is likewise the case with Advanced Math.avail/. These files, Avail.avail and Advanced Math.avail, respectively, are representatives.

A representative is just an ordinary module, but it serves a special role. The contents of a package are only visible to modules recursively contained within the package; they are not visible to modules outside this package. The sole exception to the rule is the representative. Given an import specification that references a package, the compiler or executor resolves the reference not to the directory itself but to its representative. It is typical for the representative to use its extended imports section to re-export names imported from other modules within the package. In this way, the representative "speaks for" the package.

Because of the module resolution process, a dependent module cannot discern the difference between a package and an ordinary module. This is a deliberate design point of Avail. It permits a large module to be refactored into a package containing many smaller modules without affecting any downstream modules.

‹ Pragmas Section | Return to Modules | Module Discovery ›