Introduced Names Section
The Names
keyword begins the introduced names section. The contents of this section are zero or more string literals separated by commas ,
(U+002C)
. Each string literal introduces an atom and exports it for use by downstream modules. For example:
In this example, Dice
is a module that defines services related to constructing and evaluating arbitrary dice expressions of the kinds prescribed by many role-playing game systems. As such, it provides dice-related services but does not consume them, i.e., it knows how to use dice but does not know why or when to do so. Dice
is a service provider, e.g., library, and its introduced names section constitutes the catalog of its available services.
By including a name in the introduced names section, the compiler or executor creates a new atom and associates it with the name. Equivalent names imported from upstream modules are shadowed by the new name. This means that an operation that resolves a name to an atom will always prefer an atom created by a locally introduced name over one imported from an upstream module. Because of this rule, the following scenario is unambiguous despite the fact that Avail
and Dimensional Analysis
each export "_+_"
:
Note that module constants and module variables cannot be exported via the introduced names section. This is because the definition of a module constant or module variable does not create a new atom or participate in name resolution, whereas the definition of a message does.
This is a design point of Avail. While it would have been easy to associate atoms with module constants and module variables, thereby making them available for export, doing so would have increased the scope of module-specific state. This, in turn, would encourage construction of spaghetti code.
It is, however, trivial for a programmer to overcome this limitation in exactly those circumstances in which she wishes to do so. First, define methods that reference the module constant or module variable. Then export the associated messages for use by downstream modules.
By forcing the programmer to build an API around module-specific state, programmers are compelled to:
- Design features rather than accrete them over time.
- Consider issues of semantic abstraction and data encapsulation.
- Consider issues of the cardinality of software features, i.e., the singleton anti-pattern.
- Consider issues of concurrent access.
In the above example, only the capabilities of reading and incrementing the counter are provided, not the capability of setting it to an arbitrary value. This API guarantees the monotonicity of the (singleton) counter.
‹ Module Name Section | | | Return to Modules | | | Entry Points Section › |