A module in m is a script (a text file) which can be loaded by other scripts, giving access to the functions and variables declared in the module.
Modules serve two purposes:
|
use >ModuleName1, >ModuleName2, ... |
This loads the modules ModuleName1, ModuleName2 and so on, and initializes them, i.e. executes their main code . Each module is only initialized once per process, even if it is loaded several times by different modules.
Module names are not case sensitive, since they are related to file names on the underlying operating system.
|
use System // load module "system" print System.appdir; // this will work print system.appdir // this is the same |
An alias name can be used in addition to the module name to denote the module, e.g. to abbreviate a long module name. Alias names are local to the module containing the use clause. Like module names, they are not case sensitive:
|
use >ModuleName as >AliasName |
As an example, consider the following module accounts maintaining a list of accounts and allowing transfers between them:
|
S=[]; // initialization of the module function get(nr) x=accounts.S[nr]; // all accounts start at zero if x=null then x=0 end; return x end function xfer(f, t, x) ..S[f]=get(f)-x; ..S[t]=get(t)+x end |
Within the functions, the global variable S must be prefixed by the module name (accounts.S), or by the double dot prefix indicating the current module (..S).
The module can then be used as follows:
|
// load the module and name it 'acc'. use accounts as acc // transfer money out of the blue to the bank acc.xfer('blue', 'bank', 100000); print acc.get('bank') → 100000
// transfer money from the bank to the Daltonsacc.xfer('bank', 'Daltons', 10000); print acc.get('bank') → 90000
// show all accountsprint acc.S → [-100000, 90000, 10000]
|
When encountering a use clause, the m compiler searches modules in the following order:
Global variables and functions must normally be prefixed by the name of the module defining them (or the corresponding alias), and a dot. The prefix for the main script and the builtin functions and variables is just a dot, without a name.
Within a module, global variables and functions of the same module can be prefixed by a double dot ..: in the code for module accounts above, ..S denotes the same variable as accounts.S.
The prefixing is not always required when the variable or function is referenced in the module containing it. Furthermore, functions declared in the main script or builtin standard functions only need a prefix if a function with the same name exists in the current module. The following table summarizes how variables and functions without module prefix are interpreted:
| Variable x | Function f | |
| main module | global .x | .f |
| function in main module | local x | .f |
| module M | global M.x | M.f if it exists, .f otherwise |
| function in module M | local x | M.f if it exists, .f otherwise |
Each module has a version, which is a number in the form major.minor; the minor component by convention has a 1/100th granularity.
The module version is a special variable version, which can only be modified in the module itself by assigning a number literal to it. If no number has been assigned, the version is 0.0. The version of an uncorrectly loaded optional module (see below) is null.
Source of module client:
|
version=1.23 |
|
use client // require at least version 1.20 of client module if client.version>=1.20 then ... end |
The version of the builtin module is always the version of the m application. See also .version.
Not all devices support all modules, or a module may simply not be installed on a device. To cope with these cases in the code, a module can be loaded in a use clause with the try prefix:
|
use try >ModuleName |
Loading a module with the try prefix has the following effects:
|
use try nirvana nirvana.f(1, 2) → ExcNotAvailable thrown
print nirvana.val→ ExcNotAvailable thrown
// nirvana.version is null: the module cannot be usedprint nirvana.version → null
use try math // there is no sinh function in module math print math.sinh(1.2) → ExcNotAvailable thrown
// math.version is not null: the module can be usedprint math.version → 1.08
|
|