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
$rootsvector, along with amodulesdirectory 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 amodulesdirectory alongside the script.) -
When Pyro is executing the REPL it adds the current working directory to the
$rootsvector.
To customize Pyro's import behaviour:
-
You can edit the
$rootsvector within a Pyro program to add or remove entries. -
You can use the
--import-rootcommand-line option to add additional root directories. -
You can use a
PYRO_IMPORT_ROOTSenvironment 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);