Modules¶
Modules are a simple way of grouping functions and global variables together. Without modules, you’d have to write all your code in a single script file. A module is therefore an additional way of structuring your code by grouping functions by theme in files, enabling code to be reused across several projects.
There are two types of module:
Built-in modules supplied directly with LocalSolver. You’ll find a full list of theses modules and their documentation on the Standard library page.
User modules. These modules are coded in LSP by you or other users and are placed alongside your other project files.
The module lookup paths¶
To search for modules, the LocalSolver interpreter will first look at the
corresponding file in the lookup paths. LocalSolver will then search in the list
of its builtin modules (such as csv
, charset
, datetime
). User
modules therefore always have priority over builtin modules.
By default, the lookup paths contains a single folder. It varies depending on how you run LocalSolver:
When using LocalSolver from the command line (with the localsolver program), the folder containing the main script supplied from the command line is considered as the lookup path, regardless of the current execution folder. So, when you call the following script
localsolver c:\localsolver\examples\toy\toy.lsp
, the lookup path is initialized to the folderc:\localsolver\examples\toy\
.When using LocalSolver with the studio, the root of your workspace is considered the only lookup path, regardless of the path to the lsp file or dashboard you’re running.
When using the modeler API (in Python, C#, Java or C++), the lookup path is initialized to your program’s current execution folder.
Create a module¶
A module is automatically created for each LSP file loaded by the interpreter. To create a new user module, simply create a new LSP file. The file must be placed in the same folder as your main LSP file. The filename without extension and path will be used as the module name. It is also possible to place your new LSP files in different folders, using compound module names as shown below.
As the file name is used as the module name, it must comply with LSP rules on
identifiers: the name must begin with a letter or the underscore character,
followed by a list of alphanumeric characters (letters, numbers or underscore).
An exception is made for the main program used as an entry point. This is the
only LSP file that is not imported using a use
directive. Consequently, its
name is free.
For instance, in the example tree below, if the $main.lsp
file is your
program’s entry point, then the foobar.lsp
file is a module that can be
loaded from your main program under the name foobar
:
/
|- $main.lsp
|- foobar.lsp
You can create or load as many modules as you like in LSP, as long as the module name is unique throughout your program.
Import a module¶
To import a module into your program, simply use the use
keyword followed
by the module name. The module is then exposed as a global variable, accessible
from anywhere in your program.
Use statements should be placed at the top of your program, after any pragma declarations but before the first class or function declarations.
Using the example given above, you can import the foobar
module from your
$main.lsp
file as follows:
use foobar;
function main() {
println("Greetings from another module:");
foobar.sayHelloWorld();
}
Rename a module¶
When you import a module, a global variable with the same name is automatically
created in your program. If this name conflicts with one of your variables, or
if you find the name too long, you can change the variable name using the
keyword as
as shown below:
// Declare a new global variable "geo" and initialize it with the module geodata
use geodata as geo;
function input() {
geo.computeMatrix(...);
}
Import specific functions or classes of a module¶
It is also possible to import specific functions and classes of a module directly into the current namespace using the following syntax:
use serialize, parse from json;
The previous example imports serialize
and parse
functions into the
current namespace. To use it, you no longer need to prefix the functions with
the module name (here json
), thus shortening the syntax. serialize
or
parse
can be used in the same way as if you had programmed them in the
current module.
Note, however, that functions and classes imported that way behave as if they had remained in their original module. They therefore only have access to their original global variables and have no access to the variables of the module into which they are imported, unless explicitely passed.
Just like the complete module, you can also rename imported functions or classes
using the as
keyword, as in the example below:
use serializer, parse as parseJson from json;
Modules located in sub-folders¶
Until now, imported modules were either builtin-modules, or modules located at the root of lookup paths (i.e. the folder containing the main script, the current execution folder or the current workspace, depending on how you call LocalSolver).
But it is also possible to import modules located in subfolders of the lookup paths. To do this, you can create as many sub-folders as you like in your lookup-paths and place your LSP files in them.
To import them, you’ll then need to write a compound module name. A compound module name is a sequence of valid LSP identifiers separated by a dot. Each intermediate identifier represents the name of one of the sub-folders. The last identifier is the name of the LSP file.
For example, if you place a file named ducks.lsp
in a birds
folder
which is itself in an animals
folder, like this:
animals/
|- birds/
|- ducks.lsp
The full module name will be animals.birds.ducks
. Unlike simple module
names, modules with compound names must be renamed with the keyword as
.
It is not possible to import them directly:
use animals.birds.ducks; // will throw an error
use animals.birds.ducks as ducks; // ok
Note that although the syntax animals.birds.ducks
seems to indicate that
module ducks
is a sub-module of birds
, this is not the case. There is no
notion of sub-modules in LSP. In the example above, there is only one module
with a compound name. Keep in mind that each module is independent of the
others, regardless of their organization in the computer’s folders.