0:08
There may be plenty of situations in which you want to execute the same section of code multiple
0:13
times in a row. A loop is a control structure that allows us to execute a statement or a group of
0:18
statements multiple times, depending on whether particular conditions are met.
0:23
In essence, when the script comes to your loop, it analyzes the condition. If the condition is true,
0:29
then it performs the conditional code and then re-analyzes the condition. It will keep doing this until
0:36
the condition is false, at which point it ignores the code.
0:40
Lua provides us with three different types of loops, which are all very similar, but have slight
0:44
variations on how they handle their conditional statements:
0:48
A While Loop repeats its code over and over again while your conditional statement is true. If
0:55
the conditional statement never changes, this loop will continues indefinitely, and will error out.
1:01
A For Loop will execute its code for a predetermined number of times, which you can define.
1:09
And a Repeat Loop will repeat its code over and over again until a specific condition is met.
1:16
Let’s build some simple loops demonstrating each of these types, and then we’ll apply them to our
1:21
Q-SYS design. First, the While loop. Let’s define variable x as 5, and we'll build a loop that will
1:29
increment x by 1 until it reaches the value of 10. So our conditional statement for while can be (x<10).
1:39
Then we add the very important reserved word of do , which starts the body of our conditional code.
1:45
We’re simply going to take x and redefine it as its current value, plus one.
1:52
Then we’ll print the new value X so we have some record of this loop occurring, and we’ll type end to
1:59
finish our do statement. When x goes into this loop the first time, it will add 1 to it,
2:05
turning x into 6, then it will print 6, and then return to the conditional statement. Since x, now
2:11
being 6, is still less than 10, it will go through the conditional code again to become 7,
2:17
then 8, then 9, then 10. Now when it reaches the conditional statement, it does not qualify as
2:25
being less than 10 anymore, so the do code is not performed, and the loop is over.
2:31
We can validate this by running our script, and we can see that our debug window prints x at the end
2:37
of each loop, and then stops. Now to our eye it appears that this all happens instantaneously rather
2:42
than sequentially, but rest assured the computer is doing one loop after the other.
2:48
Next let’s do a For Loop. This is a determinate loop, which will only run once for every
2:55
iteration that we specify. I’ll remove the while conditional statement and replace it with for i=1,5.
3:06
Here, i represents an iteration, or an instance of the loop. The first number here will be the
3:11
number we start at, and the second number is the number we want to stop at. If we run it now, it
3:17
will appear to do the same thing as our previous loop. On the 1st iteration it ran this loop and changed
3:24
x to 6, on the second iteration it did this loop and changed x to 7, etc. After the fifth iteration, x is 10
3:32
and the loop is finished. But the reason why it’s finished is completely different than our previous
3:37
example. In our while loop it finished because X no longer met the conditional statement, but in this
3:43
loop it finishes because it has simply terminated its instructions on how many times to run.
3:49
I also want to point out that i has nothing to do with x, nor does it have to start at 1. I could have this
3:57
run from 22 to 26, and it would give us the same results. It runs a loop for 22, another for 23, 24, 25,
4:05
and 26. This is simply a range, but the 22nd iteration does the exact same thing as the 1st iteration.
4:14
Lastly, let’s write a repeat loop. Once again I’ll keep my conditional code, but let’s replace this first
4:21
line with the command repeat. The biggest difference here is that the repeat loop doesn't start with
4:27
the conditional statement, it ends with it. This means it performs its first loop no matter what, and
4:33
then validates whether it should continue after that loop is complete. As far as our syntax goes, this
4:39
means we don’t need anything other than the word repeat to begin our loop. We can also replace
4:44
end with our conditional statement of until. Now we define what that conditional statement is: in
4:51
this case, x is equivalent to 10. It’s a very similar concept to the while loop, but the while loops
4:59
performs its analysis first and then does the work, while the repeat loop does the work first, and
5:04
then analyzes if it should continue.
5:07
So let’s combine this with some of the other tools we’ve learned so far to make a loop that’s actually
5:12
useful to us. We could use a loop, for instance, to simplify an otherwise repetitive script. Take a look
5:19
at this Scriptable Controls component– … in which we've added five Toggle buttons named “Flippy”,
5:24
and inside we’re using the first Flippy’s EventHandler to launch a function. This function
5:32
contains an if/then statement. If Flippy’s Value is 1, then its .Legend reads ON. Else, its Legend reads
5:41
OFF. We can see that this works, our button displays the appropriate label based on this script. But
5:48
that only works for the first button. If I wanted to give every button this same behavior, I’d have to
5:54
duplicate this script four more times, right? Well, not necessarily – because we could use a for loop.
6:01
Instead, I can simply add a for conditional statement, for i=1,5 do … and then it will do this script.
6:13
All I need to do is replace the index of each control – rather than reference that first control’s
6:18
number, I’m going to reference the ith control – in this case, it’s going to use our iteration number as
6:25
a variable to apply within our function. So on the first iteration it writes this function for Flippy
6:31
number 1, on the second iteration it writes this function for Flippy number 2, etc. All I need to do is
6:37
end my for loop at the bottom here, and my work is done. Every one of my controls now has the
6:44
same behavior, and I did it with just two lines of code rather than dozens. If you start scaling this
6:51
up to a lot more than five controls, you can see how much time and processing it could save you.
6:56
Also, we see here an example of why our iterations in a for loop don’t always have to start at 1.
7:02
I could define this for loop to run from iterations 2 through 5 instead, which would only affect
7:09
controls 2 through 5, if I wanted 1 to have some different type of behavior.
7:14
Alright, let’s swap over to the Block Controller and build all these loops there. You’ll find the loops
7:20
under the Flow Control section. First, let’s grab this Repeat block. This should look familiar, it’s
7:27
currently set to a while conditional statement, or you could change its dropdown to an until
7:33
conditional statement. Just like we did in Lua, we’ll establish a variable and set it to 5, and then we’ll
7:41
perform our while loop with the condition that x is less than 10. So we’ll need to grab a logic
7:47
operator and change it to “less than,” and we’ll go to our variables and grab our x, and then grab a
7:55
value for the second half and set that to 10. For the mouth of our statement, or the “do” section,
8:03
we’ll go back to variables and set x to something else. We need to do some arithmetic here so
8:10
we’ll go back to operators and grab this addition block. Once again we can grab our x variable for the
8:17
first slot and a value of 1 for our second slot. All that’s left is to go to the System folder and grab a
8:27
debug print block, and have it print our new x.
8:34
Alright, if we look at these two side by side, they are the exact same thing. X equals 5, and while X is
8:41
less than ten, we add one to x, and print it. In fact, if we look at the Lua output of the block controller,
8:49
we can see that it is generating the exact same Lua, word for word, as the while loop that we wrote
8:55
ourselves. HOWEVER. I want to point something out to you. Let’s change this while loop to a
9:02
repeat-until loop. On the Lua side you’ll remember that this means we move the conditional
9:08
statement to the very end. On the block side, we simply need to change the while to until. But let's
9:15
also adjust our conditional statements so it will repeat until x is greater than 9, which will give us
9:21
the same results as our previous script, and I’ll do that on both sides. Arlgiht, so far so good! But look
9:27
at the Lua code the Block Controller is generating. Rather than writing a true repeat-until loop, it
9:36
simply changes its while loop with a “not” modififer. While X is NOT greater than 9.
9:44
Sure, it does the same thing for now … but there’s one special case where this might be problematic.
9:50
I mentioned earlier that the repeat loop performs its loop first, and then checks its conditional
9:56
statement to see if it should continue. So what if the conditional statement is already met before
10:01
the loop begins? I’ll change the until to be greater than 0 rather than greater than 9.
10:10
When x starts at 5, it’s already greater than 0. A Lua repeat loop will still, regardless, run through
10:17
its loop once before checking its conditions – so we get a debug showing us that it went through one
10:24
cycle before realizing the condition is met and it stops itself. But the Block Controller is still a while
10:31
loop in disguise – so it checks the condition first: and since 5 is already greater than zero, it doesn’t
10:39
perform the loop at all. So these two functions may appear to be identical, but we get a slightly
10:45
different result. This probably won’t ever be a big deal for you, but I thought it was worth
10:50
mentioning. Alright, finally, let’s build our For loop with the Block Controller. We’ll replace the
10:56
repeat block with this “for each item” loop. The body of this loop will stay the same, but we need an
11:03
Array to define how many times we perform this action. We haven’t played with arrays yet, but
11:09
just think of an array as a bucket with multiple items organized in it. This block says it’s going to
11:16
perform this action once for each item in the bucket, so we simply need to define a bucket that fits
11:22
5 things. I’ll grab this block, that creates an array with blank repeated blank times. It doesn’t matter
11:31
what items are actually in the array, it just cares how many of them there are. So I could create an
11:37
array with anything in the world, a number, a string, whatever, and I’ll repeat it as many times as I
11:43
want the loop to run. When I update the script, our loop performs as expected.
11:50
Alright, that’s just an overview on loops. You can get far more complicated with what loops do –
11:56
including nesting loops inside of loops, but we’re not going to go any deeper in this online course.
12:02
Take a look at our control worksheet on Loops, and then move on whenever you’re ready.