Variables

What are Variables?

Variables are very important to scripting in Setup Factory. Variables are simply “nicknames” or “placeholders” for values that might need to be modified or re-used in the future. For example, the following script assigns the value 10 to a variable called “amount.”

amount = 10;

Note: We say that values are “assigned to” or “stored in” variables. If you picture a variable as a container that can hold a value, assigning a value to a variable is like “placing” that value into a container. You can change this value at any time by assigning a different value to the variable; the new value simply replaces the old one. This ability to hold changeable information is what makes variables so useful.

Here are a couple of examples demonstrating how you can operate on the “amount” variable:

amount = 10;
amount = amount + 20;
Dialog.Message("Value", amount);

This stores 10 in the variable named amount, then adds 20 to that value, and then finally makes a message box appear with the current value (which is now the number 30) in it.

You can also assign one variable to another:

a = 10;
b = a;
Dialog.Message("Value", b);

This will make a message box appear with the number 10 in it. The line “b = a;” assigns the value of “a” (which is 10) to “b.”

Variable Scope

As mentioned earlier in this document, all variables in Setup Factory are global by default. This just means that they exist project-wide, and hold their values from one script to the next. In other words, if a value is assigned to a variable in one script, the variable will still hold that value when the next script is executed.

For example, if you enter the script:

foo = 10;

...into screen’s On Preload event, and then enter:

Dialog.Message("The value is:", foo);

...into the screen’s On Next event, the second script will use the value that was assigned to “foo” in the first script. As a result, when the Next button is clicked, a message box will appear with the number 10 in it.

Note: The order of execution is important...in order for one script to be able to use the value that was assigned to the variable in another script, that other script has to be executed first. In the above example, the screen’s On Preload event is triggered before the screen’s On Next event, so the value 10 is already assigned to foo when the On Next event’s script is executed.

Local Variables

The global nature of the scripting engine means that a variable will retain its value throughout your entire project. You can, however, make variables that are non-global, by using the special keyword “local.” Putting the word “local” in front of a variable assignment creates a variable that is local to the current script or function.

For example, let’s say you have the following three scripts in the same project:

Script 1:

-- assign 10 to x
x = 10;

Script 2:

local x = 500;
Dialog.Message("Local value of x is:", x);
x = 250; -- this changes the local x, not the global one
Dialog.Message("Local value of x is:", x);

Script 3:

-- display the global value of x
Dialog.Message("Global value of x is:", x);

Let’s assume these three scripts are performed one after the other. The first script gives x the value 10. Since all variables are global by default, x will have this value inside all other scripts, too. The second script makes a local assignment to x, giving it the value of 500—but only inside that script. If anything else inside that script wants to access the value of x, it will see the local value instead of the global one. It’s like the “x” variable has been temporarily replaced by another variable that looks just like it, but has a different value.

(This reminds me of those caper movies, where the bank robbers put a picture in front of the security cameras so the guards won’t see that the vault is being emptied. Only in this case, it’s like the bank robbers create a whole new working vault, just like the original, and then dismantle it when they leave.)

When told to display the contents of x, the first Dialog.Message action inside script #2 will display 500, since that is the local value of x when the action is performed. The next line assigns 250 to the local value of x—note that once you make a local variable, it completely replaces the global variable for the rest of the script.

Finally, the third script displays the global value of x, which is still 10.

Variable Naming

Variable names can be made up of any combination of letters, digits and underscores as long as they do not begin with a number and do not conflict with reserved keywords.

Examples of valid variables names:

a
strName
_My_Variable
data1
data_1_23
index
bReset
nCount

Examples of invalid variable names:

1
1data
%MyValue%
$strData
for
local
_FirstName+LastName_
User Name

Reserved Keywords

The following words are reserved and cannot be used for variable or function names:

and                  break                do                    else                       elseif
end                  false                 for                    function                 if
in                     local                 nil                     not                        or
repeat              return               table                 then                      true
until                  while

Types and Values

Setup Factory’s scripting language is dynamically typed. There are no type definitions—instead, each value carries its own type.

What this means is that you don’t have to declare a variable to be of a certain type before using it. For example, in C++, if you want to use a number, you have to first declare the variable’s type and then assign a value to it:

int j;
j = 10;

The above C++ example declares j as an integer, and then assigns 10 to it.

As we have seen, in Setup Factory you can just assign a value to a variable without declaring its type. Variables don’t really have types; instead, it’s the values inside them that are considered to be one type or another. For example:

j = 10;

...this automatically creates the variable named “j” and assigns the value 10 to it. Although this value has a type (it’s a number), the variable itself is still typeless. This means that you can turn around and assign a different type of value to j, like so:

j = "Hello";

This replaces the number 10 that is stored in j with the string “Hello.” The fact that a string is a different type of value doesn’t matter; the variable j doesn’t care what kind of value it holds, it just stores whatever you put in it.

There are six basic data types in Setup Factory: number, string, nil, boolean, function, and table. The sections below will explain each data type in more detail.

Number

A number is exactly that: a numeric value. The number type represents real numbers—specifically, double-precision floating-point values. There is no distinction between integers and floating-point numbers (also known as “fractions”)...all of them are just “numbers.” Here are some examples of valid numbers:

4             4.            .4           0.4            4.57e-3             0.3e12

String

A string is simply a sequence of characters. For example, “Joe2” is a string of four characters, starting with a capital “J” and ending with the number “2.” Strings can vary widely in length; a string can contain a single letter, or a single word, or the contents of an entire book.

Strings may contain spaces and even more exotic characters, such as carriage returns and line feeds. In fact, strings may contain any combination of valid 8-bit ASCII characters, including null characters (“\0”). Setup Factory automatically manages string memory, so you never have to worry about allocating or de-allocating memory for strings.

Strings can be used quite intuitively and naturally. They should be delimited by matching single quotes or double quotes. Here are some examples that use strings:

Name = "Joe Blow";
Dialog.Message("Title", "Hello, how are you?");
LastName = 'Blow';

Normally double quotes are used for strings, but single quotes can be useful if you have a string that contains double quotes. Whichever type of quotes you use, you can include the other kind inside the string without escaping it. For example:

doubles = "How's that again?";
singles = 'She said "Talk to the hand," and I was all like "Dude!"';

If we used double quotes for the second line, it would look like this:

escaped = "She said \"Talk to the hand,\" and I was all like \"Dude!\"";

Normally, the scripting engine sees double quotes as marking the beginning or end of a string. In order to include double quotes inside a double-quoted string, you need to escape them with backslashes. This tells the scripting engine that you want to include an actual quote character in the string.

The backslash and quote (\") is known as an escape sequence. An escape sequence is a special sequence of characters that gets converted or “translated” into something else by the script engine. Escape sequences allow you to include things that can’t be typed directly into a string.

The escape sequences that you can use include:

\a   -   bell
\b   -   backspace
\f   -   form feed
\n   -   newline
\r   -   carriage return
\t   -   horizontal tab
\v   -   vertical tab
\\   -   backslash
\"   -   quotation mark
\'    -   apostrophe
\[   -   left square bracket
\]   -   right square bracket

So, for example, if you want to represent three lines of text in a single string, you would use the following:

Lines = "Line one.\nLine two.\nLine three";
Dialog.Message("Here is the String", Lines);

This assigns a string to a variable named Lines, and uses the newline escape sequence to start a new line after each sentence. The Dialog.Message function displays the contents of the Lines variable in a message box, like this:


 

Another common example is when you want to represent a path to a file such as
C:\My Folder\My Data.txt. You just need to remember to escape the backslashes:

MyPath = "C:\\My Folder\\My Data.txt";

Each double-backslash represents a single backslash when used inside a string.

If you know your ASCII table, you can use a backslash character followed by a number with up to three digits to represent any character by its ASCII value. For example, the ASCII value for a newline character is 10, so the following two lines do the exact same thing:

Lines = "Line one.\nLine two.\nLine three";
Lines = "Line one.\10Line two.\10Line three";

However, you will not need to use this format very often, if ever.

You can also define strings on multiple lines by using double square brackets ([[ and ]]). A string between double square brackets does not need any escape characters. The double square brackets lets you type special characters like backslashes, quotes and newlines right into the string. For example:

Lines = [[Line one.
Line two.
Line three.]];

is equivalent to:

Lines = "Line one.\nLine two.\nLine three";

This can be useful if you have preformatted text that you want to use as a string, and you don’t want to have to convert all of the special characters into escape sequences.

The last important thing to know about strings is that the script engine provides automatic conversion between numbers and strings at run time. Whenever a numeric operation is applied to a string, the engine tries to convert the string to a number for the operation. Of course, this will only be successful if the string contains something that can be interpreted as a number.

For example, the following lines are both valid:

a = "10" + 1; -- Result is 11
b = "33" * 2; -- Result is 66

However, the following lines would not give you the same conversion result:

a = "10+1"; -- Result is the string "10+1"
b = "hello" + 1; -- ERROR, can’t convert "hello" to a number

For more information on working with strings, see the topic String Manipulation.

Nil

Nil is a special value type. It basically represents the absence of any other kind of value.

You can assign nil to a variable, just like any other value. Note that this isn’t the same as assigning the letters “nil” to a variable, as in a string. Like other keywords, nil must be left unquoted in order to be recognized. It should also be entered in all lowercase letters.

Nil will always evaluate to false when used in a condition:

a = nil;
if a then
    -- Any lines in here
    -- will not be executed
end

It can also be used to “delete” a variable:

y = "Joe Blow";
y = nil;

In the example above, “y” will no longer contain a value after the second line.

Boolean

Boolean variable types can have one of two values: true, or false. They can be used in conditions and to perform Boolean logic operations. For example:

boolybooly = true;
if boolybooly then
     -- Any script in here will be executed
end

This sets a variable named boolybooly to true, and then uses it in an if statement. Similarly:

a = true;
b = false;
if (a and b) then
     -- Any script here will not be executed because
     -- true and false is false.
end

This time, the if statement needs both “a” and “b” to be true in order for the lines inside it to be executed. In this case, that won’t happen because “b” has been set to false.

Function

The script engine allows you to define your own functions (or “sub-routines”), which are essentially small pieces of script that can be executed on demand. Each function has a name which is used to identify the function. You can actually use that function name as a special kind of value, in order to store a “reference” to that function in a variable, or to pass it to another function. This kind of reference is of the function type.

For more information on functions, see the topic Functions.

Table

Tables are a very powerful way to store lists of indexed values under one name. Tables are actually associative arrays—that is, they are arrays which can be indexed not only with numbers, but with any kind of value (including strings).

Here are a few quick examples (we cover tables in more detail in the topic Tables(Arrays):

Example 1:

guys = {"Mark", "Lorne", "Darryl"};
Dialog.Message("Second Name in the List", guys[2]);

This will display a message box with the word “Lorne” in it.

Example 2:

t = {};
t.FirstName = "Michael";
t.LastName = "Jackson";
t.Occupation = "Singer";
Dialog.Message(t.FirstName, t.Occupation);

This will display the following message box:

You can assign tables to other variables as well. For example:

table_one = {};
table_one.FirstName = "Michael";
table_one.LastName = "Jackson";
table_one.Occupation = "Singer";
table_two = table_one;
occupation = table_two.Occupation;
Dialog.Message(table_one.FirstName, occupation);

Tables can be indexed using array notation (my_table[1]), or by dot notation if not indexed by numbers (my_table.LastName).

Note that when you assign one table to another, as in the following line:

table_two = table_one;

...this doesn’t actually copy table_two into table_one. Instead, table_two and table_one both refer to the same table.

This is because the name of a table actually refers to an address in memory where the data within the table is stored. So when you assign the contents of the variable table_one to the variable table_two, you’re copying the address, and not the actual data. You’re essentially making the two variables “point” to the same table of data.

In order to copy the contents of a table, you need to create a new table and then copy all of the data over one item at a time.

For more information on copying tables, see the topic Tables.

Variable Assignment

Variables can have new values assigned to them by using the assignment operator (=). This includes copying the value of one variable into another. For example:

a = 10;
b = "I am happy";
c = b;

It is interesting to note that the script engine supports multiple assignment:

a, b = 1, 2;

After the script above, the variable “a” contains the number 1 and the variable “b” contains the number 2.

Tables and functions are a bit of a special case: when you use the assignment operator on a table or function, you create an alias that points to the same table or function as the variable being “copied.” Programmers call this copying by reference as opposed to copying by value.