Imports
An import declaration brings names from a package into the current scope. Every path starts with a package, and nothing from another package — not even a fully qualified path — can be named without an import.
import-decl = "import" package { "::" segment } [ "::" ( "*" | "{" name { "," name } [ "," ] "}" ) ] ";"
segment = identifier | "#" identifier
name = identifier | "#" identifier
Forms
| Form | Brings in | Used as |
|---|---|---|
import Pkg::Item; | one root item of Pkg | Item |
import Pkg::Mod; | a module of Pkg | Mod::Item |
import Pkg::Mod::Item; | one item of a module | Item |
import Pkg::{ A, B, #target }; | several items or modules from one place | A, B, #target |
import Pkg::Mod::{ A, B }; | several items of one module | A, B |
import Pkg::*; | every public root item and top-level module of Pkg | each by its name |
import Pkg::Mod::*; | every public item of a module | each by its name |
import Pkg; | Pkg's module named Pkg, when it has one | Pkg::Item |
import Io::PrintLine; // a root item
import Core::{ #target, int8 }; // a compile-time value and a primitive's constants
import Tally::{ Counter, Level }; // two items from one package
import Shapes::Square; // a whole module
import Shapes::Square::Perimeter; // one item of a module
import Shapes::Circle::*; // every public item of a module
func Main() -> int {
var counter = Counter(3);
counter.Tick();
PrintLine("{} {}", counter.Count(), Level::Low == Level::Low);
PrintLine("{} {} {}", Square::Area(5), Perimeter(5), Diameter(2));
PrintLine("{} {}", int8::Max, #target.pointerBits);
return 0;
}
Importing a module rather than its items keeps calls qualified, which is the better choice whenever a bare name would be unclear or would collide: Square::Area(5) says which Area is meant.
import Pkg; on its own names a module, not the package: it works only when Pkg declares a module called Pkg (pub module Pkg { … }). Otherwise it is an error — import an item or a module instead:
error: import 'Io' does not name a module
help: import an item instead, for example 'import Io::Name'
The first segment is a package
The first segment of every import is a package's import name:
- the current package's own
NamefromRux.toml— a package imports its own nested modules this way, as inimport Geometry::Shape::Circle;; - or a key under
[Dependencies]. The key is usually the package's name, but it may differ, which renames the package for imports: withShapes = { Package = "Geometry2", Path = "../Geometry2" }, the example above imports fromShapes.
A first segment that is neither fails before analysis starts:
error: package 'Shape' is not listed in [Dependencies] of '…\Rux.toml'
note: the import requires a package dependency with the same import name
help: add the package under [Dependencies] or correct the import path
The remaining segments walk the package's modules. An item or module that is not there is reported as name 'Gauge' was not found in package 'Tally' or module 'Counter' was not found in package 'Tally'.
Qualified paths need an import
A path in an expression or a type starts from a name already in scope. Another package's name is never in scope by itself, so a fully qualified call does not work:
func Main() -> int {
return Tally::Clamp(12); // error: name 'Tally' is not defined in this scope
}
Import the item, or the module that contains it, and qualify from there. Inside one package, every root item and every top-level module is already in scope, so Shape::Circle::Area(2.0) works without an import from anywhere in the package that declares Shape — see Name lookup.
Compile-time values and primitive constants
Imports also reach two kinds of name that look built in but are declared by the Core package:
- Compile-time values and directives are imported by their
#names:import Core::{ #target, #build, #Error };. Without the import,#target.osfails witherror: name '#target' is not defined in this scope. See Compile-time context. - Associated constants of primitive types —
int8::Max,uint::Bits,float64::NaN— come fromCore's declarations of those types, so the type must be imported:import Core::int8;. The primitive type itself is usable without any import; only its constants need one. Without it:
error: 'Max' not found in extend for type 'int8'
The full list of primitive constants is in Primitive types; how a package declares them is in Intrinsics.
Where imports go
An import is a declaration. It may appear at the package root, inside a module body, and inside a when branch; in a when match arm the trailing ; is optional. An import inside a module applies to that module and the modules nested in it. It cannot appear inside a function body:
error: expected an expression before 'import'
By convention each file starts with the imports it uses.
rux 0.4.0 places an import written at the top of a file into the package root, so the other files of the package can see it too. Do not rely on that: write in each file the imports that file uses. Associated constants are already strict about it —
int8::Max is found only in a file that itself imports int8.Glob imports
import Pkg::*; and import Pkg::Mod::*; bring in every public name at that level — items, and with the package form also its public top-level modules. Private declarations are skipped silently, so a glob never fails on them; naming a private item explicitly does fail:
error: function 'Clamp' is private to package 'Tally'
help: add 'pub' to the declaration of 'Clamp'
A glob makes it hard to see where a name came from, and grows when the package does. Prefer a list.
Conflicts
An imported function joins the overload set of a function with the same name already in scope. Two candidates that accept the same arguments make every call ambiguous:
error: call to 'Validate' is ambiguous: 2 overloads accept argument types ()
help: rename one of the overloads, or remove a default value that makes them overlap
Import the module instead and qualify the call.
See also
- Packages and modules — what a path walks through
- Visibility — which names another package can import
- Dependencies — the
[Dependencies]table that supplies import names - Learn: Module, Dependency