The following table lists keywords and statements that can be used in a script for better control flow.
...
Name
...
Description
...
if
…else
...
The if
statement executes some specified instructions if the condition is true. Otherwise, the else
statement can be used to execute a different set of instructions. else if
can be used to specify an alternative condition with different instructions. Once an if
or else if
statement is executed, any following else if
statements will not be executed.
...
while
...
A while
loop will repeatedly execute until the condition expression becomes false
.
...
do
…while
...
The do
statement allows you to execute the contents of a while
loop at least once before the condition is evaluated. If the condition is true
, the loop will repeat as usual until the while
condition becomes false
.
...
for
...
A for
loop repeats until a specified condition becomes false
. Below is the standard syntax used by a for
loop:
Code Block | ||
---|---|---|
| ||
for (<initialExpression>; <conditionExpression>; <incrementExpression>) {
// instruction code
} |
A for
loop can also be used to iterate over arrays and objects, as explained below.
...
break
...
Terminates a switch
statement, a while
loop, or a for
loop completely. The break
statement prevents the execution of the following case
s in a switch
statement. Adding a break
statement to each case
is good practice.
...
continue
...
The continue
statement terminates the execution of the current iteration in a loop and then executes the next iteration. Unlike break
, this statement does not terminate the loop completely.
...
switch
…case
...
The switch
statement lets you compare an input value to the value of each case
. If matched, the instruction code for that case is executed. Otherwise, the default
instruction code is executed. Each case
statement should usually be followed by a break
statement.
...
default
...
The default
statement specified what should happen if a switch
statement does not match any of the cases. A break
statement is not required.
...
function
...
A function is a block of code designed to perform a particular task. Functions can take in a set of arguments and can return a value. Functions are one of the primary methods for organizing and re-using code.
...
return
...
Ends the function execution, and the function will return the specified value to the caller.
...
arguments
...
Can be used within a function to get a list of values that were passed into the function call.
Examples for if
…else
and else if
:
In this example, a notification saying “boolTag is true” will be displayed if the tag’s value is true.
Code Block |
---|
if (tag.read("boolTag")) notification.send("boolTag is true."); |
You can execute multiple lines of code after an if
statement by enclosing the code in curly braces:
Code Block |
---|
if (tag.read("boolTag")) {
notification.send("boolTag is true.");
thread.sleep(1);
} |
In the example below, if tag “A” equals 1, assign 100 to tag “B”. If “A” equals 2, assign 200 to “B”. Otherwise, assign 500 to “B”.
Code Block | ||
---|---|---|
| ||
var value = tag.read("A");
if (value == 1) {
tag.write("B", 100);
} else if (value == 2) {
tag.write("B", 200);
} else {
tag.write("B", 500);
} |
Note that the if
and else if
conditions must be enclosed in parentheses.
...
The tag "A" will be incremented from 0 to 100 over the course of one second:
Code Block | ||
---|---|---|
| ||
var val = 0;
while (val <= 100) {
tag.write("A", val);
val = val + 1;
thread.msleep(10);
} |
Example for do
…while
:
The tag “boolTag” will be toggled at least once. If the tag “doLoop” is true after one second, “boolTag” will continue to toggle once per second. Once “doLoop” becomes false
, the toggling will stop and the script will end.
Code Block |
---|
do {
tag.write("boolTag", !tag.read("boolTag"));
thread.sleep(1);
} while (tag.read("doLoop")); |
Examples for for
A for
loop lets you provide 3 expressions that define the behavior of the loop.
The first expression will be run once before the loop first executes. Typically, this is used to initialize a counter variable like
i
orj
.The second expression is a condition that will be checked before each execution of the loop. If the condition is
false
, the loop will not execute, and thefor
loop will end. Typically, this is used to check if the counter variable has reached some value.The third expression is run at the end of each execution of the loop. Typically, this is used to increment the counter variable.
In this example, the initial value of i
is 0. When i
is less than or equal to 100, i
will increment by 1 and store the result in the tag The following table lists keywords and statements that can be used in a script for better control flow.
Name | Description | |||||
| The | |||||
| A | |||||
| The | |||||
| A
A | |||||
| Terminates a | |||||
| The | |||||
| The | |||||
| The | |||||
| A function is a block of code designed to perform a particular task. Functions can take in a set of arguments and can return a value. Functions are one of the primary methods for organizing and re-using code. | |||||
| Ends the function execution, and the function will return the specified value to the caller. | |||||
| Can be used within a function to get a list of values that were passed into the function call. | |||||
| The | |||||
| Throws an |
Examples for if
…else
and else if
:
In this example, a notification saying “boolTag is true” will be displayed if the tag’s value is true.
Code Block |
---|
if (tag.read("boolTag")) notification.send("boolTag is true."); |
You can execute multiple lines of code after an if
statement by enclosing the code in curly braces:
Code Block |
---|
if (tag.read("boolTag")) {
notification.send("boolTag is true.");
thread.sleep(1);
} |
In the example below, if tag “A” equals 1, assign 100 to tag “B”. If “A” equals 2, assign 200 to “B”. Otherwise, assign 500 to “B”.
Code Block | ||
---|---|---|
| ||
var value = tag.read("A");
if (value == 1) {
tag.write("B", 100);
} else if (value == 2) {
tag.write("B", 200);
} else {
tag.write("B", 500);
} |
Note that the if
and else if
conditions must be enclosed in parentheses.
Examples forwhile
:
The tag "A" will be incremented from 0 to 100 over the course of one second:
Code Block | ||
---|---|---|
| ||
var val = 0;
while (val <= 100) {
tag.write("A", val);
val = val + 1;
thread.msleep(10);
} |
Example for do
…while
:
The tag “boolTag” will be toggled at least once. If the tag “doLoop” is true after one second, “boolTag” will continue to toggle once per second. Once “doLoop” becomes false
, the toggling will stop and the script will end.
Code Block |
---|
do {
tag.write("boolTag", !tag.read("boolTag"));
thread.sleep(1);
} while (tag.read("doLoop")); |
Examples for for
A for
loop lets you provide 3 expressions that define the behavior of the loop.
The first expression will be run once before the loop first executes. Typically, this is used to initialize a counter variable like
i
orj
.The second expression is a condition that will be checked before each execution of the loop. If the condition is
false
, the loop will not execute, and thefor
loop will end. Typically, this is used to check if the counter variable has reached some value.The third expression is run at the end of each execution of the loop. Typically, this is used to increment the counter variable.
In this example, the initial value of i
is 0. When i
is less than or equal to 100, i
will increment by 1 and store the result in the tag “FOR_VAL” every iteration until i
equals 100. Once i
equals 100, the for
loop will end.
Code Block | ||
---|---|---|
| ||
for (var i = 0; i <= 100; i++) { tag.write("FOR_VAL", i) thread.msleep(100) } |
Looping Over Arrays
A for
loop can also be used to iterate through arrays using the array index.
Code Block |
---|
// Define an array var myArray = [ "val1", "val2", "val3" ] // Get the indices for (var index in myArray) { notification.send(index); } // 0, 1, 2 // Get the values for (var index in myArray) { var value = myArray[index]; notification.send(value); } // val1, val2, val3 |
Looping Over Objects
A for
loop can also be used to iterate through objects using keys.
Code Block |
---|
// Define an object var myObject = { "key1": "val1", "key2": "val2", "key3": "val3" } // Get the keys for (var key in myObject) { notification.send(key); } // key1, key2, key3 // Get the values for (var key in myObject) { var value = myObject[key]; notification.send(value); } // val1, val2, val3 |
Example forcontinue
The continue
keyword can be used in a while
or for
loop to move to the next iteration without breaking out of the loop. This can be used to skip specific items.
...
Code Block | ||
---|---|---|
| ||
for (var i = 0; i < 10; i++) { if (i == 5) { continue; } notification.send(i); } // 0, 1, 2, 3, 4, 6, 7, 8, 9 |
Examples for switch
…case
, break
, and default
In this example, when the script executes, the tag "REPLY" will be assigned the string value "Hello, <name>" by default. If the name entered is empty, the “REPLY” tag will be set to "Could not load name." instead.
...
The break
statement is used to break out of the switch
statement and prevent any other case
s from executing. If break
is not used, then multiple cases may be executed. This can lead to unexpected behavior, so in most cases, each case
should have a break
statement.
Examples for function
,return
, and arguments
...
Code Block | ||
---|---|---|
| ||
function multiply(a, b) { return a * b; } var x = multiply(4, 3); // x is now equal to 12 |
Optional Arguments
Functions do not need to have any arguments. For example, here is a function that outputs a message, waits for 3 seconds, then exits the project.
...
In the example below, the function multiplyDefault
returns a * b
if both a
and b
are specified. If b
is not specified, the function instead returns a * 10
.
Code Block |
---|
Code Block |
function multiplyDefault(a, b) {
if (b === undefined) {
b = 10;
}
return a * b;
}
multiplyDefault(2, 3); // 6
multiplyDefault(2); // 20 |
The arguments
keyword
There is also a special keyword arguments
, which gives an array containing the values passed into the function call. This allows functions to use a variable number of arguments.
Code Block |
---|
function returnFirstArg() {
return arguments[0];
}
returnFirstExtraArg("a", "b", "c"); // "a" |
You can also use arguments
in a function definition, in which case arguments
will only include values not covered by the named arguments. This is useful when you know that the first few arguments are required, but any additional arguments are optional.
Code Block |
---|
function returnFirstExtraArg(x, y, arguments) {
return arguments[0];
}
returnFirstExtraArg("a", "b", "c"); // "c" |
Examples for try
…catch
and throw
A try
…catch
statement can be used to gracefully handle situations that would normally cause the script to terminate. If the code in the try
block fails, this error is returned to the catch
block, which either makes use of or ignores the error.
In the catch
statement, you must give a name for the error from the try
block. It is common practice to use the name error
.
The throw
statement can be used to manually create an error. This is mainly useful when used within a try
block, since the custom Error
object can then be used by the catch
block.
However, throw
can also be used outside of a try
block, in which case the entire script will terminate with an error. This can be useful for scripts that are called via system.importScript
, or when you need to prevent the rest of the script from executing.
Checking Whether a Tag is Loaded or Not
When a project first starts, some tags may not be loaded yet, in which case tag.read
or tag.write
will throw an error. Remote tags may take a few seconds to load, depending on the polling rate, communication method, and the size of the project.
The example script below would run on project startup and wait for a remote tag to load (become readable). Once we know that the tag can be read, we can run the rest of our startup actions (which might make use of the tag).
Code Block |
---|
// Inside main startup script "Startup1"
var loading = true;
var waited = 0;
while (loading) {
try {
tag.read("remoteTag");
loading = false;
} catch (error) {
if (waited > 10000) {
throw Error('Could not load tag "remoteTag" after 10 seconds. Please check the connection and restart the project.');
}
thread.msleep(100);
waited += 100;
}
}
// Now do any other startup actions |
Checking an Error Code From a Tag
The example below checks the value of an error code tag “errorCode” before attempting to turn a motor on using the tag “motorOn”. Depending on the error encountered (if any), the script will display a different notification. If there is a problem with tag.read
or tag.write
, this will also be handled using the notification instead of terminating the script.
Code Block |
---|
try { var errorCode = tag.read("errorCode"); switch (errorCode) { case 0: tag.write("motorOn", true); break; case 1: throw Error("Power Disconnected"); break; case 2: throw Error("Mechanical Failure") break; case 3: b = 10; throw Error("Invalid Operation Mode") } return a * b; } multiplyDefault(2, 3); // 6 multiplyDefault(2)break; // 20 |
The arguments
keyword
There is also a special keyword arguments
, which gives an array containing the values passed into the function call. This allows functions to use a variable number of arguments.
Code Block |
---|
function returnFirstArg() { return arguments[0]; } returnFirstExtraArg("a", "b", "c"); // "a" |
You can also use arguments
in a function definition, in which case arguments
will only include values not covered by the named arguments. This is useful when you know that the first few arguments are required, but any additional arguments are optional.
Code Block |
---|
function returnFirstExtraArg(x, y, argumentsdefault: throw Error("Unrecognized Error Code") } } catch (error) { return arguments[0]; } returnFirstExtraArg("a", "b", "c"); // "c"var errorString = "Could not turn on motor: " errorString += error.message; notification.send(errorString) } |
Built-In Functions for Script Importing and Execution
Canvas also provides some built-in functions which allow you to utilize scripts from within other scripts.
Name | Description |
| Calls another script in the project directly by name. This pauses the calling script until the target script finishes executing. This can also be used to import functions and variables from other scripts. |
| When an external program is called directly, the caller will be in standby mode until the called program (the external program) ends its operation. However, if an external program is called using |
Examples forsystem.importScript
and system.runScript
Both system.importScript
and system.runScript
can be used to execute scripts in the project from within another script. The difference is that importScript
runs the script in the same thread, and runScript
runs the script in a different thread.
Say we have 3 To compare the two functions, consider these scripts “A”, “B”, and “C”:
...
Code Block |
---|
// C notification.send("In C"); |
Running Scripts in Order
We can use system.importScript
to execute the scripts in order, like so:
...
While the target script is running, the calling script is paused. If there is an error in the target script, the calling script will have an error as well.
Running Scripts Immediately
Scripts can also be run in parallel using system.runScript
. This immediately runs begins running the script on another thread.
...
With runScript
, as soon as the target script begins, the calling script resumes execution.
Note that with this method, runScript
you cannot guarantee the order of execution. In this case, the order of steps 1 and 2 may be reversed, as well as steps 4 and 5.
Importing Functions and Variables
system.importScript
can be used to import functions and variables from other scripts. In this example, we have a script called "myFunctionScript", which has a function fib
that returns the Fibonacci sum:
Code Block |
---|
// myFunctionScript function fib(n) { if (n <= 0) { return 0; } else if (n == 1) { return 01; } else if{ (n == 1) { return fib(n - return 11) + fib(n - 2); } else { return fib(n - 1) + fib(n - 2); } } } |
If we want to use the function fib
in a different script, we just need to import "myFunctionScript" first:
Code Block |
---|
system.importScript("myFunctionScript");
notification.send(fib(7)) // 13 |
This also works with variables. For example, say we have another script called “myVariableScript”:
Code Block |
---|
// myVariableScript
var x = 7; |
We could then load the variable x
as follows:
Code Block |
---|
system.importScript("myVariableScript");
notification.send(x); // 7 |
Getting a Return Value From a Script
system.importScript
returns the value of the last expression in the target script.
Here is a simple example where the target script returns the value 12. This value is then used in the calling script.
Code Block |
---|
//targetScript
var x = 7; |
If we want to use the function fib
and the variable x
in a different script, we just need to import "myFunctionScript" first:
Code Block |
---|
x + 5; |
Code Block |
---|
// Calling Script var returnValue = system.importScript("myFunctionScripttargetScript"); notification.send(fib(xreturnValue)); // fib(7) -> 1312 |