Using Modules
As we have already seen, the use construct brings members of a module into local scope.
For example, given the program:
mod Paint {
pub enum Color {
case Red, Green, Blue
}
pub type alias Hue = Color
pub def isWarm(c: Color): Bool =
match c {
case Color.Red => true
case Color.Green => false
case Color.Blue => false
}
}
All of the following uses are meaningful:
use Paint.Color
use Paint.Color.{Red, Green, Blue}
use Paint.Hue
use Paint.isWarm
All Kinds of Uses
Flix supports several kinds of uses, including:
- A qualified use of a name:
use Paint.Color. - A qualified use of multiple names:
use Paint.Color.{Red, Green, Blue}. - A qualified use with rename:
use Paint.{Color => Shade}. - A qualified use with multiple renames:
use Paint.Color.{Red => R, Green => G, Blue => B}.
A rename is always written inside braces, even when we rename a single name.
Note: Flix does not support wildcard uses.
Note: A use must be qualified. We cannot write
use Paint, and we do not have to: a top-level module, such asPaintorList, is always in scope.
Uses of a Package
A use can also reach a module of a Flix package that the project depends on. We
write the mount of the package, the name it is declared under in flix.toml,
followed by :::
use game::Board // a top-level module of the package
use game::Game.Rules // a nested module
use game::Game.Rules.players // a function
use game::{Board, Game} // several modules
use game::Game.Rules.{players => count} // with a rename
The :: separates the package from the module path inside it, and the module
path is separated by . as always: we write use game::Game.Rules, never
use game::Game::Rules. There must be no whitespace around the ::, and it can
occur at most once in a use.
A use that names no package is unaffected: use Chain.Empty reaches the
standard library, and use Paint.Color reaches our own module, exactly as
before.
Note: The
::can be written in auseonly. We cannot writegame::Board.place()in an expression, norgame::Boardin a type.
See Using Dependencies for how a package is mounted.
Where can Uses Occur?
Flix supports uses in three places:
- At the top of a file.
- Inside modules.
- Inside functions.
A use at the top of a file, or inside a module, must be written before the declarations of that file or module.
For example:
mod A {
use Chain.Empty
use Chain.One
use Chain.Chain
use Int32.max
pub def maxValue(c: Chain[Int32]): Int32 =
match c {
case Empty => 0
case One(x) => x
case Chain(x, y) => max(maxValue(x), maxValue(y))
}
}
which can also be written as:
mod A {
pub def maxValue(c: Chain[Int32]): Int32 =
use Chain.Empty;
use Chain.One;
use Chain.Chain;
use Int32.max;
match c {
case Empty => 0
case One(x) => x
case Chain(x, y) => max(maxValue(x), maxValue(y))
}
}
Note the use of semicolons when inside an expression.
Default Uses
In Flix, a few built-in constructors are always in scope:
List.NilandList.Cons.Option.NoneandOption.Some.Result.OkandResult.Err.