115 Using Declarations
A using declaration adds component aliases or selected imported names to the
current source file's lexical name-resolution context. It affects name resolution only; it
does not create schema-evolution release metadata.
A source file uses using to reference any available component. This is sufficient for
Predica used as a contract language, or for other uses without a DBMS persistence and schema
evolution contract.
Schema evolution has a separate requirement: when serialised representations depend on types
implemented by another component, the component manifest's releases block records the
dependency's release number. That requirement is independent of ordinary name lookup.
Every source file has a standard prelude scope that makes selected std declarations available
unqualified and makes std available as an explicit component qualifier. This prelude is a
language rule, not a hidden using std; declaration.
Syntax
using ComponentName;
using ComponentName as Alias;
using ComponentName { QualifiedName1, QualifiedName2 as Alias2, ... };
File scope and ordering
Using declarations are file scoped. They affect only the Predica file in which they appear.
If two files in the same component need the same imported names, both files must declare the
relevant using declarations.
An ordinary source file starts with a component declaration when the file records a
filesystem-location check, then an @dynamic directive when the file opts into dynamic
variables, followed by zero or more using declarations, followed by all ordinary declarations
and top-level statements. This is the position for using declarations.
Component aliases
A declaration of the form using C; is syntactic sugar for
using C as A;, where A is the final segment of the component name
C. The implicit alias behaves identically to an explicitly declared alias.
using acme.Geometry;
using acme.Physics as phys;
value Example
{
Geometry.Point point;
phys.Vector momentum;
}
A component alias enables qualified lookup through that component. It does not import every declaration from that component as an unqualified name. To use an imported declaration unqualified, use a selected import.
The implicit std qualifier behaves like a component alias for qualification
purposes. The standard-library chapter defines the standard declarations with an explicit
std.Name spelling.
Selected imports
A declaration of the form using C { ... }; imports selected declarations from
component C under unqualified local names. A selected name is qualified within
the imported component when it names a nested declaration.
using acme.Geometry { Point, Shapes.Circle as Disk };
using acme.Math { pi, sin };
Nameimports the declarationC.Nameunder the local nameName.Qualified.Nameimports the declarationC.Qualified.Nameunder the local nameName.Qualified.Name as Aliasimports the declaration under the local nameAlias.- A selected import does not introduce an alias for the component as a whole.
Selected imports name exported types, type aliases, constants, functions, procedures, folds,
generic declarations, and namespaces. Importing a function name imports every overload of that
name. A selected spelling that matches more than one non-function declaration kind in the
imported component is ambiguous and is rejected at the using declaration.
Visibility and qualification
- Declarations in the same component as the current file are visible through the current namespace chain.
- Component aliases permit qualified names such as
Geometry.Point. - Selected imports permit unqualified names such as
Pointor aliases such asDisk. - Imported declarations are never discovered merely because another component exists under an include root.
Ambiguity of unqualified names
- Multiple imported non-function declarations introducing the same unqualified name make that name ambiguous.
- Imported functions with the same unqualified name are merged into one overload set.
- An unqualified use of an ambiguous imported name is a compile-time error.
- Component aliases and selected-import aliases with distinct local names resolve ambiguity.
- A local declaration in the current component namespace chain wins over imported names.
Using statement stability rule
Rule: A using statement is
- allowed to make a program with type errors no longer have type errors
- allowed to make a program with no type errors now have type errors because of ambiguity
- never allowed to silently cause a program without type errors to produce different behaviour
A using statement alters the set of available names and type relationships while
preserving the behaviour of all previously well-typed programs. It does not silently change
the meaning of equality, embeddings, function calls, folds, or any expression whose typing and
semantics were previously determined.