
| Exiting a Loop | |
| Exiting a Loop in Perl | |
| Exiting a Loop in Windows PowerShell | |
| Exiting a Loop in VBScript |
Are you the kind of person who just loves to write loops? You know, do loops, for loops, maybe even a few for each loops? Well, in that case, we’ve got good news for you: you’re going to have a great time during this year’s Scripting Games.
For some reason, the events in this year’s Scripting Games all seem to use a lot of loops, including nested loops. (That is, loops within other loops.) That’s fine; regardless of the scripting language you’re using writing a simple little loop (e.g., one that counts from 1 to 100) is no big deal. The only problem, of course, is that many of the loops you’re going to need to write aren’t quite that simple: you might count from 1 to 100, but, then again, you might not. For example, suppose you have a loop that runs until x is equal to 37. How many times will you run through that loop? Who knows; you’ll just keep going until x is equal to 37. And then, the moment that x is equal to 37, you need to exit the loop immediately.
Which is also fine. Unless, of course, you don’t know how to exit a loop. In that case, you’ve got major problems.
Unless, of course, you read the rest of this week’s tip.
To exit a loop in Perl (any kind of loop) all you have to do is call the last statement. For example, suppose we have a loop that counts from 1 to 1,000,000:
for ($i = 1; $i <= 1000000; $i++)
{
print "$i\n";
}
As you can see, we have a very simple for loop here. The loop starts off with $i equal to 1, and continues to run as long as $i is less than or equal to 1,000,000; each time we run through the loop we do two things: we increment the value of $i by 1 ($i++) and we print the current value of $i:
1 2 3 4 5 6 7 … 1000000
Now, that’s all well and good, but suppose we want to exit that loop if $i is equal to 5. How can we do that? You got it: we simply include an if statement that checks to see if $i is equal to 5 (if ($i == 5)). If $i is equal to 5 we then use the last statement to immediately break out of the loop:
for ($i = 1; $i <= 1000000; $i++)
{
print "$i\n";
if ($i == 5) {last}
}
What’s going to happen when we run this script? This is what’s going to happen:
1 2 3 4 5
That’s it: as soon as $i is equal to 5 the last statement causes us to exit the loop. Just that easy, just that quick.
Now let’s take a look at a more complicated scenario: a loop inside a loop. Here’s a for loop that’s nested inside another for loop:
for ($y = 1; $y <= 5; $y++)
{
print "Loop number $y\n";
for ($i = 1; $i <= 3 ; $i++)
{
if ($y == 2) {last}
print "$i\n";
}
}
In this case, the outer loop runs from 1 to 5, echoing the statement Loop number x each time. In addition, each time we go through the outer loop we execute a nested for loop; this one prints the numbers 1 through 3. After one iteration of the loop we should – and do – see the following:
Loop number 1 1 2 3
So far so good. Notice, however, that our nested loop includes an exit condition: if $y is equal to 2 we want to break out of the loop:
if ($y == 2) {last}
Here’s what happens when we run this modified script:
Loop number 1 1 2 3 Loop number 2 Loop number 3 1 2 3 Loop number 4 1 2 3 Loop number 5 1 2 3
That’s pretty good; as you can see, when $y was equal to 2 we exited the interior loop. But suppose we wanted to exit the exterior loop; that is, suppose we wanted to exit both loops. The last statement isn’t going to do it, at least not by itself.
We’ve got a problem.
Or do we? As it turns out, Perl allows you to attach a label to any loop. For example, this line of code names a loop OutsideLoop:
OutsideLoop: for ($y = 1; $y <= 5; $y++)
Why would you want to name a loop? Well, for one thing, we can then specify which loop we want to exit simply by adding the name of that loop to the last statement. For example:
OutsideLoop: for ($y = 1; $y <= 5; $y++)
{
print "Loop number $y\n";
for ($i = 1; $i <= 3 ; $i++)
{
if ($y == 2) {last OutsideLoop}
print "$i\n";
}
}
Notice what we do now if $y is equal to 2. We don’t just call the last statement, which causes us to exit the current loop. Instead, we add the name of the loop (OutsideLoop) that we want to exit. In this case, that’s going to cause us to exit both loops:
{last OutsideLoop}
Now look at our script output:
Loop number 1 1 2 3 Loop number 2
That’s more like it.
With a few minor syntactic differences, Windows PowerShell uses the same approach to exiting loops as Perl does. For example, here’s a sample script that sets up a for loop designed to run from 1 to 1,000,000. If the counter variable $i is equal to 5, however, the script exits the loop:
for ($i = 1; $i -le 1000000; $i++)
{
$i
if ($i -eq 5) {break}
}
As you can see, this is very similar to the Perl script for exiting a loop. The two big differences? Well, an obvious one is the fact that Windows PowerShell uses a different set of operators than Perl. In Perl you use this syntax:
if ($i == 5)
In PowerShell, the same command is written like this:
if ($i -eq 5)
In addition, PowerShell uses the break statement (as opposed to the last statement) in order to exit a loop. Other than that, however, the two approaches are very similar.
The same thing is true when trying to exit multiple loops with a single command: the general approach is the same, although the syntax is a little different. Let’s take a look at the PowerShell version, then point out how it differs from its Perl equivalent:
:OutsideLoop for ($y = 1; $y -le 5; $y++)
{
write-host "Loop number $y"
for ($i = 1; $i -le 3 ; $i++)
{
if ($y -eq 2) {break OutsideLoop}
$i
}
}
As you can see, PowerShell also enables us to attach a label to a loop. The syntax, however, is the exact opposite of the syntax used by Perl. With Perl a label consists of a name followed by a colon:
OutsideLoop:
In PowerShell, a label consists of a colon followed by a name:
:OutsideLoop
Why? No idea; that’s just the way the two languages work.
And, of course, in PowerShell you again use the break statement followed by the loop name:
{break OutsideLoop}
Is that going to break us out of both loops with a single command? Let’s try running the script and see for ourselves:
Loop number 1 1 2 3 Loop number 2
Well what do you know?
VBScript (bless its heart) takes a somewhat different approach to this problem. VBScript actually has two commands for exiting loops: you call the Exit Do statement to exit a Do loop, and the Exit For statement to exit a For (or For Each) loop. For example, here’s how we exit a basic For loop in VBScript:
For i = 1 to 1000000
Wscript.Echo i
If i = 5 Then
Exit For
End If
Next
That’s not so bad. In fact, compared to the last statement (which might not be the best name ever given to a scripting command), it’s not bad at all.
The one problem with VBScript’s approach to exiting loops is this: you can’t give your loops a name. Why is that a problem? Well, suppose we have the following script:
For y = 1 to 5
Wscript.Echo "Loop number " & y
For i = 1 to 3
If y = 2 Then
Exit For
End If
Wscript.Echo i
Next
Next
As you can see, in this script we use the Exit For statement to exit the interior loop. But what if we wanted to exit both loops at the same time? Uh-oh. Now we have a problem, because we can’t specify which loop to exit. Instead, all we can do is call Exit For, which can only exit the current loop.
So what are we supposed to do? Well, admittedly, this is a bit of a kludge. But it works:
For y = 1 to 5
Wscript.Echo "Loop number " & y
For i = 1 to 3
If y = 2 Then
y = 6
Exit For
End If
Wscript.Echo i
Next
Next
Here we’re again using the Exit For statement to exit the inside loop. But notice the line of code immediately preceding Exit For:
y = 6
What’s the point of this? Well, Exit For will break us out of the inside loop; however, that won’t have any effect on the outside loop. What will have an effect on the outside loop is changing the value of y to 6; that’s because the loop is designed to run only as long as y is equal to a value between 1 and 5. As soon y is equal to 6 the loop automatically comes to a halt.
Give it a try and you’ll see what we mean.
Another option is to use two different types of loops; for example, this script uses a For Next loop nested inside a Do Until loop:
y = 1
Do Until y > 5
Wscript.Echo "Loop number " & y
For i = 1 to 3
If y = 2 Then
Exit Do
End If
Wscript.Echo i
Next
y = y + 1
Loop
By doing this we can call the Exit Do loop in order to exit our Do Until loop. And because the For Next is tucked inside the Do loop, that will cause us to exit the For Next loop as well:
Loop number 1 1 2 3 Loop number 2
A little crazy, but it works.
Just like the Scripting Guys.
Well, except maybe for the part about working.