Skip to main content

Constants And Enumerations

Contents

Introduction

Squirrel allows you to define constants: fixed values which will never change while the application is running. Constants are useful because they allow you to represent numeric or string values with easy-to-read alternatives, making your code easier to read, understand and maintain. When you upload your code to the impCloud, every one of those constants is replaced by the value for which it is a substitute.

Constants

Constants are declared using the const keyword:

const VON_KLITZING_CONSTANT = 25812.8074434;

Only integers, floats or strings can be declared as a constant.

It is conventional, but not mandatory, to set constant names in uppercase, with words separated by underscores, as shown above.

Enumerations

Enumerations sequences of related constants. They are declared using the enum keyword and the result if a set of constants identified by the enumeration’s name and the name of the member constant within it. The enumeration’s name is followed by its members (separated by commas) in braces:

enum LIST {
    FIRST,
    SECOND,
    THIRD
};

server.log(LIST.THIRD);
// Displays '2'

As you can see from the example above, if no values are specified, the first member of the enumeration takes the value zero, with each subsequent member taking the value of one more than its predecessor. Unlike other languages, while the first item on the list may be assigned an index value, the other members’ values will not be calculated from this value. Instead, the first unspecified constant will always be set to zero and subsequent members’ values calculated from that. For example, in the following code, LIST.FIRST is set to 10, but LIST.SECOND, because its value is not specified, is set to 0. LIST.THIRD is also unspecified, so it is set to LIST.SECOND plus 1, ie. 1:

enum LIST {
    FIRST = 10,
    SECOND,
    THIRD
};

server.log(LIST.THIRD);
// Displays '1'

Enumerations can be of mixed types, but each member constant can only be an integer, float or string:

enum LIST {
    FIRST = 10,
    SECOND = "this is a string",
    THIRD = 99.999
};

In this respect, enumerations can be viewed as simple table literals, but you should note that, unlike tables, enums cannot be declared using JSON syntax, and you cannot create a new table from an enumeration. For example, the follow code will not compile:

enum LIST {
    FIRST = 10,
    SECOND = "this is a string",
    THIRD = 99.999
};

local t = LIST;

However, the new table’s value can be set from the enum:

enum LIST {
    FIRST = 10,
    SECOND = "this is a string",
    THIRD = 99.999
};

local t = {};
t.key <- LIST.SECOND;

When Constants And Enumerations Are Evaluated

Constants and enumerations are evaluated when the Squirrel is compiled into the bytecode which is run within the device and agent virtual machines. As such, the constant does not exist until the compiler reaches the declaration. From this point, any subsequent code can reference the constant, but code prior to the definition will not be able to access the value as it has not at that time been resolved by the compiler. For example, this code:

function displayValue() {
    local a = MY_CONSTANT;
    server.log(a);
}

const MY_CONSTANT = 42;

displayValue();

will fail with the error "ERROR: the index 'MY_CONSTANT' does not exist" because the reference to MY_CONSTANT within the function declaration was left untouched by the compiler — it didn’t yet know that MY_CONSTANT is a constant. Only when it reaches the const keyword does it ‘know’ that MY_CONSTANT is a constant of value 42.

The following code will run successfully because the constant declaration comes first, allowing the compiler to correctly resolve the statement within the subsequent function declaration:

const MY_CONSTANT = 42;

function displayValue() {
    local a = MY_CONSTANT;
    server.log(a);
}

displayValue();

This circumstance is particularly relevant when declaring classes. Constants that will be used in class instances must be declared before the class is itself declared:

const CONSTANT_ONE = "Forty-two";
const CONSTANT_TWO = 42;

class Universe {

    constructor(answer = CONSTANT_TWO) {
        server.log(answer);
    }
}

Finally, a further example of (re)declaration order:

const CONSTANT_ONE = "Forty-two";

class C {
    function f() {
        const CONSTANT_ONE = 42;
    }
}

const CONSTANT_ONE = 42.0024;

C.f();

server.log(CONSTANT_ONE);

This will log 42.0024. This is because the Squirrel interpreter’s pass through the code looking for constants establishes the value of CONSTANT_ONE first as "Forty-two" then as 42 and finally as 42.0024, and then it runs the code. When function f() is called, CONSTANT_ONE has already been set to 42.0024 (the declaration within the function is ignored at this point) so that is the value logged.


Back to the top