Skip to content

Variables

A variable is a unit of data that is stored in memory for future use, by the application. There are four key aspects to a variable: 1. Its name 2. Whether or not it is allowed to be changed 3. The type of data it is allowed to store 4. When it can be used 5. How it is used as an input for functions


Variable Names

You can give a variable any name you like, so long as it abides by the following rules:

  • It must begin with a letter
  • It can include letters, numbers, and underscores ("_")
  • It cannot include spaces or other special characters
  • You cannot use a name that is already being used by Modulo1, (e.g. "number", "melody", "autoDesigner")
  • You cannot reuse a name that you have already used for a class definition

Here are some examples of valid names: "foo_bar", "square34", "donkeyKong", "AllYourBassAreBelongToUs"

Here is an example of a variable in use:

1
var foo_bar = 21;

The keyword var tells Modulo1 that we want to create a new variable. We have chosen the name foo_bar to identify our variable. And we have assigned the value of 21 to it. Alternatively, if we are not yet ready to assign a value to our variable, we can do this instead:

1
var foo_bar;

This line of code tells Modulo1 that we want to create a variable, but also that we are not ready to give it a proper value. For now, its value will be null. We can set its value later, to any of Modulo1's data types.

Here is an example of how we can delay the setting of its value:

1
2
var foo_bar;
foo_bar = 10003;

Notice that we do not use the keyword var at when setting the value. That is because our variable was already created (with the var keyword) in the previous line of code.

We can create several empty variables at the same time:

1
var foo_bar1, foo_bar2, foo_bar3;

Or we can choose to give some (or all) of them values during their creation:

1
var foo_bar1, foo_bar2 = 56, foo_bar3 = "Hello";

Is it changeable?

Any variable created with the var keyword is able to be changed later on in the code. But it is also possible to create a variable that is permanent and unchangeable. You can achieve this by using the const keyword instead of the var keyword. Like this:

1
const foo_bar = 21;

Now, if you accidentally write code that attempts to change this variable, Modulo1 will declare an error.


The Types of Data

As soon as we create a new variable, we are provided with an opportunity to assign a value to it. The data type of this value will automatically be detected by Modulo1 and then Modulo1 will assume that this variable will always hold that data type. After this, if you try to change the variable to a different type, Modulo1 will declare an error and stop your code.

The exception to this, is if you change your variable to null. Doing so will immediately reset your variable and allow it to receive any kind of data.


array is a data type for storing an ordered list of values. Each item in an array may be a different data type

1
var notes = [27, 100.298, "pencil", true];

boolean is a data type for storing either true or false

1
var didIBrushMyTeeth = true;

class_object is a data type for storing class objects.

1
var bear = animal("Bear");

drumRiff is a data type for composing drum riffs

1
var myRiff = drumRiff(16 beats);

musicalTime is a data type for expressing the amount of time that compositions and notes play for

1
var myDuration = 1 beat;

function is a data type for creating functions.

1
2
3
var myFunc = function(number x, number y) returning null {
    return x * y;
}

iterator is a data type for navigating through an array, object, or numberRange. It is mostly used in for loops.

1
2
3
for (var n in notes) {
    print(n);
}

melody is a data type for composing instrument melodies.

1
var myGroove = melody(96 ticks);

null is a unique data type in that it is not really anything. It is really the absence of data

1
var myValue = null;

number is a data type for storing a number

1
var myNumber = 36.76343;

numberRange is a data type for specifying a range of numbers that are evenly spaced apart.

1
var r = between 10 to 20;

object is a data type for storing an unordered collection of values. Each item in an object may be a different data type and each item within an object is identified by its own name.

1
var notes = { age : 27, speed : 100.298, item : "pencil", windy : true };

string is a data type for storing unformatted text

1
var myText = "Hello World!";

When Your Variable Can Be Used

Info

There is a notable exception to the following rules about code blocks: class definitions have internal code blocks that behave quite differently to what is described in this section.

All Modulo1 code exists within code blocks. Here is an example of a code block:

1
2
3
tracks {

};

If you create a variable inside this block, that variable will be available for the duration of the block. But as soon as Modulo1 reaches the closing curly brace }, your variable will no longer be available. For example, the following is invalid:

1
2
3
4
5
6
7
tracks {
    var myBeat = |X--X--xX-X---X--|;
};

composition (1 bar) {
    print(myBeat);
};

This will cause an error because the variable myBeat is only available within the tracks code block.

In some cases, there are code blocks inside of other code blocks. For example:

1
2
3
4
5
6
7
tracks {
    function setWidth(number x) {
        var width = x;
    };

    setWidth(24);
};

In this example, we have a variable called width and it is inside a function called setWidth. Functions are also a type of code block. So, the variable width actually belongs to the setWidth function and is not available to the other code within the tracks block. For example, the following is invalid:

1
2
3
4
5
6
7
8
tracks {
    function setWidth(number x) {
        var width = x;
    };

    setWidth(24);
    var height = width * 2;
};

This will cause an error because the variable width is only available within the setWidth function.

Here are some other examples of code blocks that take ownership of variables:

while statements:

1
2
3
4
5
6
7
8
tracks {
    var count = 0;

    while (count < 10) {
        var width = count * 4;
        count += 1;
    };
};

do while statements:

1
2
3
4
5
6
7
8
tracks {
    var count = 0;

    do {
        var width = count * 4;
        count += 1;
    } while (count < 10);
};

for loops:

1
2
3
4
5
6
7
tracks {
    var allAges = [34, 23, 37];

    for (var age in allAges) {
        var height = age / 2;
    }
}

Info

For more information about these kinds of statements, check out our page on flow control

Another issue to be aware of, is that it is possible to reuse the name of a variable in multiple blocks, even if a block is inside another block. For example:

1
2
3
4
5
6
7
8
tracks {
    var myBeat = |X---X---|;

    for (var i in 1 to 10) {
        var myBeat = drumRiff(8);
        myBeat.compose();
    }
}

In this example, a variable called myBeat is created inside the tracks code block. Then, inside a for loop we have created another variable called myBeat. In fact, every time that the loop begins the variable myBeat is created and when the loop restarts the myBeat variable is automatically deleted. Modulo1 allows this, and will not throw an error here.

The compose() function is run on every cycle of the loop. And each time, it will access the version of myBeat that was created within the for statement.

You might be wondering how Modulo1 decides which version of a variable to use. The answer is simple: Modulo1 begins its search for a variable within the current code block, and if it fails to find one there, it will search in the code block that surrounds the current one, and then the code block that surrounds that one, on and on again, until it runs out of surrounding code blocks. If Modulo1 runs out of code blocks to search within, it will give up the search and throw an error.


How your variables are passed around

Like, the Java and JavaScript languages, Modulo1 treats simple variables (null, boolean, number, and string) different than how it treats complex variables (array, object, iterator, melody, drumRiff, class_object).

When a simple variable is used as the input to a function, Modulo1 makes a copy of that variable and sends the copy to become the input of the function. This means that if the function makes changes to the variable, it will not affect the original variable: the changes will only occur to the copy of the variable. For example:

1
2
3
4
5
6
7
var myAge = 32;

function double(number age) {
    age *= 2;
}
double(myAge);
print(myAge);

In this example, we use the variable myAge as the input to the function double(). Modulo1 creates a copy of myAge and then allows double() to refer to this copy as age. So, when double() performs calculations upon age, our original variable myAge is not affected. When we print myAge, we will see: 32.

On the other hand, when a complex variable is used as the input to a function, Modulo1 does not make a copy. Instead, Modulo1 sends the original version to the function. This means that if the function makes changes to the variable, it will affect the original variable. For example:

1
2
3
4
5
6
7
var dreamCars = ["BMW", "Ferrari", "Porsche"];

function addHonda(array cars) {
    cars.addToEnd("Honda");
}
addHonda(dreamCars);
print(dreamCars);

In this example, we use the variable dreamCars as the input to the function addHonda(). Modulo1 allows addHonda() to refer to the original version of dreamCars as cars. So, when addHonda() adds a new value to the end of cars, or original variable dreamCars is affected. When we print dreamCars, we will see: ["BMW", "Ferrari", "Porsche", "Honda"]

This behavior also occurs when you save a variable to a new location, such as into an array, an object, or just under a new variable name. Simple variables will be duplicated, when saved to a new location, but complex variables will not. A consequence of this behavior, is that a complex variable can exist in an unlimited amount of locations at any one time. For example:

1
2
3
4
5
6
7
8
9
var colors = ["Red"];
var colors2 = colors;
colors2.addToEnd("Blue");

var things = { one : colors2 };
things["one"].addToEnd("green");

colors2.addToStart("Orange");
print(colors);

In this example, we assigned our original array colors to many locations. We assigned it to colors2. Then we added "Blue" to colors2. Next, we assigned colors2 to the one element of things. Finally, we added "Orange" to the start of colors2. If colors had been a simple variable, such as a string, then it would never have been changed in this example. A copy would have been made each time it was assigned to a new location and at each location the changes there would not affect any other locations. But instead, because Modulo1 recognises colors as an array, it means that its value was never copied. The exact same copy of the exact same value is being held by several variables. So, when one of these variables is changed, all of them are changed. When we print colors, we will see: ["Orange", "Red", "Blue", "green"]