Websites Navigation: Airbit | Shop | m-shell.net
Languages: EN | DE

Modules

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:

  • They help in structuring complex scripts and make them easier to understand and maintain.
  • They offer a way of extending the functionality of m by adding new functions which can then be used by all scripts or interactive m sessions. Entire libraries of often needed functions can be created that way. The standard library of m described in the next chapter is organized into modules.
To load a module, a use clause is required:

use ModuleName1ModuleName2, ...

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 Daltons
acc.xfer('bank', 'Daltons', 10000);
print acc.get('bank')
→ 90000
// show all accounts
print acc.S
→ [-100000, 90000, 10000]

Module Search Order

When encountering a use clause, the m compiler searches modules in the following order:

  1. The list of installed native modules (the location of native modules is defined by the system and cannot be changed).
  2. The directory of the script being compiled.
  3. The Library Path folders in the order they were added, i.e. listed in the libpath property.
  4. The m application directory (const system.appdir).

Module Prefixes

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 xFunction f
main moduleglobal .x.f
function in main modulelocal x.f
module Mglobal M.xM.f if it exists, .f otherwise
function in module Mlocal xM.f if it exists, .f otherwise

Module Version

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.

Optional Modules

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:

  • If the module and all the modules it uses are correctly loaded, the result is almost the same as without try. However, a reference to an undeclared function or variable of the module will not be detected until the code reaches the corresponding statement and throws ExcNotAvailable. This allows to run code even if some functions or variables of a module do not exist.
  • If the module ModuleName itself or one of the modules it uses is not found or cannot be loaded, no error is marked. However, all references to its variables and functions will result in ExcNotAvailable being thrown; only the module's version variable is accessible and will return null.
Special care must be taken when creating .mex files from code which loads modules as optional: modules, functions or variables unavailable when compiling the code will never become available, even if the .mex file is executed in an environment providing them. Hence you should always compile the code on a platform supporting all desired functionality.

use try nirvana
nirvana.f(1, 2)
→ ExcNotAvailable thrown
print nirvana.val
→ ExcNotAvailable thrown
// nirvana.version is null: the module cannot be used
print 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 used
print math.version
→ 1.08

ModuleImportList := use ModuleImport { ',' ModuleImport } .
ModuleImport := [try] ModuleName [as AliasName] .
AliasName := Identifier .


© 2004-2011 airbit AG, CH-8008 Zürich
Document AB-M-REF-887
mShell Home  > Documentation  > Manuals