114 Namespaces

Predica declarations are organised using components and namespaces. A component is the filesystem and dependency unit. Namespaces organise declarations inside one component.

Where Predica is used in a computer system, a component is typically associated with a deployment unit such as a library containing implementations of the types and functions belonging to that component. In a legal system, components are typically associated with the division into parts, such as acts or articles.

Namespaces are used to organise declarations and to avoid accidental name collisions. A namespace does not create a component dependency, and a folder inside a component does not create a namespace. Namespaces must be declared explicitly in Predica source.


namespace Geometry
{
    value Point
    {
        Real x;
        Real y;
    }

    namespace Shapes
    {
        value Circle
        {
            Point centre;
            Real radius;
        }
    }
}

Namespace lookup

Within a namespace, unqualified component-local names are resolved relative to the current namespace and then its ancestor namespaces, stopping at the root namespace of the current component. A more local declaration hides a declaration with the same name in an ancestor namespace.


value Thing {}

namespace Inner
{
    value Thing {}

    value Use
    {
        Thing x;  // resolves to Inner.Thing
    }
}

If Inner did not declare Thing, the reference would continue to the component root namespace and find the outer Thing.

Qualified names inside a component

Qualified names that are not component aliases are interpreted relative to the current component namespace chain. For a reference to A.B inside acme.Model.Geometry.Units, lookup may try:


acme.Model.Geometry.Units.A.B
acme.Model.Geometry.A.B
acme.Model.A.B

Lookup does not continue to acme.A.B or to any other component merely because the component names share a dotted prefix. Component namespace ancestry organises components; it does not create implicit dependencies between them.