1.9 Namespaces
A dotted module import as convert.fahrenheit_to_celsius or class field accessors as Posn.x and Posn.y demonstrate the use of hierarchical names. Other hierarchical names provided by rhombus include List.length and List.cons via List (where lists will discussed more in Lists):
> List.length(["a", "b", "c"])
3
Use the namespace form to create a namespace without creating a separate module. The identifier after namespace is bound as a namespace, and export provide forms within the namespace body determine the bindings that can be accessed from the name with the . operator.
A name defined with namespace can be used with import, but the name must be prefixed with . to distinguish it from a module path. Also, import can be used in nested blocks generally, such as a block created with block or def:
> also_pi
3.14
Naturally, namespaces can be nested further, either by exporting an existing namespace or by nesting namespace forms.
A . can be used in an import form as a shorthand to reach a nested binding without making intermediate bindings visible.
> block:
length(["a", "b", "c"])
3
An existing namespace can be extended by using a dotted name in a definition, such as defining geometry.e in a context where geometry is a namespace. The extension does not mutate the namespace; it merely extends the bindings that are available in the scope of the extending definition.
> block:
geometry.e
2.71
> geometry.e
e: identifier not provided by geometry
When a namespace is exported, any extensions of the namespace visible at the export site are also exported. Multiple extensions of a namespace can be imported into a context as long as the extensions do not conflict, which is partly a result of the rule that the same name can be imported into a context multiple times as long as the binding is always the same.