Variables¶
A variable refers to a value. A variable is identified by its name. A variable has no type. The type is hold by the value. Thus, a variable can hold values of different types. For example the following code is valid:
x = 2;
x = "a";
Variables are always assigned by reference and have global or local visibility.
The default value for a variable is nil
.
Global variables¶
Global variables are attached to modules. They are available from all the
functions declared in the same module. Global variables do not need to be
declared before use. The default value of a global variable is nil
. It’s the
default visibility for implicitly declared variables.
Example:
i = 15; // Declare and assign global variable i
println(i, j); // Use variable i and j. J is implicitly declared
Local variables¶
A local variable is only available in the block of code defining that variable and in blocks enclosed in its defining block. These blocks are called the scope of the variable. Local is the default visibility for:
Parameters of functions
Loop variables used in a for statement
Loop variables used in an iterated function call
Loop variables used in an iterated assignment
Exception variable used in a try/catch clause
Resource variable used in a with statement
Users can also introduce local variables with the local
keyword.
Introducing a local variable when a global variable with the same name is
already defined will cause this name to be associated to the local variable
in its visibility scope. Introducing a local variable when a local variable
with the same name is already defined and visible from the current code block
will throw an error. Thus, only one local variable with the same name is allowed
for any scope in the program.
For example the following code will throw the error
Variable 'i' already defined.
:
function foo(i) {
for [i in 0...10] print(i);
}
On the contrary the following code is valid since i=2
introduce i
as
a global variable which will merely be masked during the for statement:
function foo() {
i = 2;
for [i in 0...10]
print(i); // the output will be 0123456789
print(i); // the output will be 2
}
List of block structures that introduces a new scope for local variables:
block statements
{ }
if, else statements
iterated assignment statements
iterated function call
try/catch statements
with statements
for loops
while, do-while loops
Memory management¶
Internally the modeler uses a reference counting mechanism to manage memory. Each value is associated to a reference counter. This counter is increased or decreased according to the operations performed on the value. When the reference counter reaches 0, the associated value is destroyed.
The reference counter is increased when:
The value is associated to a local variable or a global variable
The value is added to a map or associated to a field of an object
The reference counter is decreased when:
The previous assigned value is replaced by a new one
The value is removed from a map or another native structure
A local variable that contains the value is destroyed
This memory management is pretty simple and has the main advantage to be completely predictable. Unfortunately, this reference counting mechanism cannot handle reference cycles, i.e a value that refers directly or indirectly to itself. So if you have to deal with very big models, try to avoid cycles.
Note
The other advantage of the reference counting is that objects are reclaimed as soon as they become unreachable. This particular behavior can be used to close automatically native ressources like files as soon as they can no longer be referenced. However, it’s better not to rely on this behavior, and instead to use the “with” statement to properly free resources that have become useless.