On this page:
namespace
8.12

6.3 Namespaces🔗ℹ

A namespace is somewhat like a module, and it is especially like a prefix given to an imported module. Unlike a module prefix, however, an existing namespace can be extended externally with additional bindings. The new bindings do not mutate the namespace, but they are visible to any use of the namespace within the scope of the extensions. Using export on a namespace also exports any extensions that are visible at the export form.

A namespace is extended though definition forms that use a .-separated sequence of identifiers as the name to bind. Where operators are allowed, the operator to define can be a .-separated sequence of identifiers followed by a . and a parenthesized operator. When using a form like expr.macro to extends a namespace, the .-separated sequence must be surrounded by pair of parentheses.

A namespace contains bindings that are in any space, while the namespace name itself is bound in the namespace space. In a given context, a dotted reference through a namespace takes precedence over interpreting the namespace identifier instead in the context’s space. For example, if p is bound as a variable whose value has an x field, and if p is also bound to a namespace that exports a x in the expression space, then p.x in an expression position refers to the export from the p namespace and not the x field of the p object. If the namespace p exports only x bindings in other spaces (such as bind or annot), then p.x refers to the x field of the p object.

definition

namespace id_name

 

definition

namespace id_name:

  nestable_body

  ...

 

definition

namespace ~open:

  nestable_body

  ...

Similar to the same nestable_body sequence spliced into the enclosing context, but definitions within the body are not visible outside the body, and export declarations are allowed and determine exports for the id_name immediately after namespace. An exported name can be reached using id_name.name. The name id_name also works with import. The id at the end of id_name is bound in the namespace space.

When ~open is supplied in place of id_name, then instead of defining a visible namespace, a private namespace name is created and also imported with import to bind all the exported name in the enclosing scope. The names are bound using the same identifiers as listed in the namespace’s export, but without scopes created by namespace to isolate other bindings within the namespace.

namespace geometry:

  export:

    pi tau

  def pi = 3.14

  def tau = 6.28

> geometry.pi

3.14

> block:

    import:

      .geometry open

    [pi, tau]

[3.14, 6.28]

namespace ~open:

  export:

    bump

  def mutable x = 0

  fun bump():

    x := x + 1

    x

> bump()

1

> x // not exported

x: undefined;

 cannot reference an identifier before its definition