Modules
- Public/Private Members
- Submodules
- Parents, Children, Siblings
- Module Caching
- Circular Imports
- Aliasing
- Importing Members
- Import Roots
- Executing Module Directories
- Assigning to members
A module is a Pyro file loaded as a library. Modules are loaded using the import
keyword.
Assume we have a file called math.pyro
containing math functions:
import math;
The imported module's name becomes a variable in the importing scope:
assert math::abs(-1) == 1;
Use the member access operator ::
to access a module's top-level members — i.e. its global variables, functions, and classes.
Public/Private Members
A module's top-level members (i.e. its global variables, functions, and classes) are private by default
— use the pub
keyword to make them public, e.g.
pub var number = 123; pub def func() { return "hello world!"; } pub class Object { var value; }
- Public members can be accessed from inside or outside the module.
- Private members can only be accessed from inside the module.
Submodules
Modules can contain submodules. Assume we have a directory called math
containing a file called trig.pyro
:
import math::trig; var value = trig::cos(1);
The top-level module math
can live alongside the directory that contains its submodules:
root/ |-- math.pyro |-- math/ |-- trig.pyro
Alternatively, it can live inside the math
directory in a file called self.pyro
:
root/ |-- math/ |-- self.pyro |-- trig.pyro
Finally, the top-level math
module can be empty and simply function as a container for its submodules:
root/ |-- math/ |-- trig.pyro
Submodules can contain submodules of their own — there's no hard limit to how deep the nesting can go.
Note that only the final module name in the import chain is declared as a variable in the importing scope, e.g.
import foo::bar::baz;
In this case, only baz
is declared as a variable in the importing scope.
Parents, Children, Siblings
Imagine we have the following module structure:
root/ |-- math/ |-- calc.pyro |-- self.pyro |-- trig.pyro
A parent module can import its child – e.g. in root/math/self.pyro
:
import math::trig;
A child module can import its parent – e.g. in root/math/calc.pyro
:
import math;
A child module can import its sibling – e.g. in root/math/calc.pyro
:
import math::trig;
Module Caching
A module is only executed the first time it's imported. The imported module is cached and any subsequent imports simply load the module from the cache.
Circular Imports
In general, circular imports are fine — module foo
can import module bar
and module bar
can import module foo
.
Note that trying to use a member from an imported module that hasn't finished initializing can result in a panic.
Aliasing
You can import a module under an alias using an import ... as ...
statement:
import math as alias; var foo = alias::abs(-1);
Submodules can similarly be aliased:
import math::trig as alias; var foo = alias::cos(1);
Importing Members
You can import a top-level member from a module by wrapping its name in braces, e.g.
import math::{abs}; assert abs(-1) == 1;
You can alias the imported member using an import ... as ...
statement, e.g.
import math::{abs} as foo; assert foo(-1) == 1;
You can import multiple members in a single import
statement by separating their names with commas, e.g.
import math::{cos, sin};
You can alias the imported members using a comma-separated as
list, e.g.
import math::{cos, sin} as foo, bar;
Import Roots
The global $roots
vector contains the list of root directories that Pyro checks when attempting to import a module.
-
When Pyro is executing a script it adds the parent directory containing the script to the
$roots
vector, along with amodules
directory within that parent directory. (This means that the modules required by a script can be located either in the same directory as the script or in amodules
directory alongside the script.) -
When Pyro is executing the REPL it adds the current working directory to the
$roots
vector.
To customize Pyro's import behaviour:
-
You can edit the
$roots
vector within a Pyro program to add or remove entries. -
You can use the
--import-root
command-line option to add additional root directories. -
You can use a
PYRO_IMPORT_ROOTS
environment variable to specify additional root directories. The value should be a list of:
separated directory paths.
Executing Module Directories
You can execute a module directory as a script if it contains a self.pyro
file, e.g.
$ pyro path/to/module/directory
Pyro executes the self.pyro
file, then the $main()
function if it finds one.
Assigning to members
Pyro doesn't allow direct assignment to module members from outside the module, e.g.
# in module.pyro pub var number = 123;
# in script.pyro import module; echo module::number; # okay module::number = 456; # syntax error
If you want to allow assignment to a module member from outside the module, use a member function, e.g.
# in module.pyro pub var number = 123; pub def set_number(new_value) { number = new_value; }
# in script.pyro import module; module::set_number(456);