- Getting Started
- Perl Variables
- Control Flow Constructs
- Altering Loop Control Flow
- A Few Special Perl Variables
- Regular Expressions
- Writing Your Own Functions
1.4 Altering Loop Control Flow
Often, the programmer needs to alter the usual behavior of loop iteration. Each of the following works equally well with any of Perl's looping constructs:
next redo last
1.4.1 last
The Perl keyword last breaks the loop and causes control to be thrown to the first statement following the loop. For example, suppose we wanted to find the index of the first negative element in an array.
#!/usr/bin/perl # # negative.pl # print "Enter some numbers "; $input = <STDIN>; @n = split(" ", $input); for ( $i = 0; $i < @n; $i = $i + 1 ) { if ( $n[$i] < 0 ) { last; } } if ($i != @n) { print "$n[$i] found at position $i in @n\n"; } else { print "no negatives found in @n"; } % negative.pl Enter some numbers 2 4 11 5 8 10 -5 found at position 3 in 2 4 11 5 8 10 %
In the above code, several numbers are entered by the user and they are split into the array @n. Next, each one is tested to see if it is less than zero. If it is, last takes control of the program to the first statement beneath the loop.
There are two paths in the program that may bring program control to the second if statement: either a negative value is found in the array or we cycle through the loop exhaustively without finding any negatives. In the latter case, the value of $i will be the same as the number of elements in the array. Otherwise, it will be different. Thus, we need to determine which case this is. The statement that controls the second if:
($i != @n)
appears to compare a scalar to an array. Whenever this is the case in Perl, the array is said to be evaluated in a scalar context. This always produces the number of elements in the array. Actually, the second part of the for loop uses a similar construction, which also causes Perl to evaluate @n in a scalar context.
$i < @n
1.4.2 next
The Perl next statement causes control of the program to jump to the next iteration of the loop. One way to think of this is that when next is executed, loop control drops to the final curly brace of the loop and then normal control is resumed. For example, to add all the positive even elements of an array, we might code as follows:
for ( $i = 0; $i < @n; $i = $i + 1 ) { if ( $n[$i] < 0 ) { next; } if ( $n[$i] % 2 == 1 ) # Note: % is the mod operator { next } $sum = $sum + $n[$i]; }
Note here that we have also used the modulus (or remainder) operator, the % symbol. This operator takes two integers and produces the remainder of dividing the first operand by the second operand. Thus, 10 % 2 is zero and 11 % 2 is one. This is one way of determining whether a number is odd or even.
1.4.3 redo
The redo statement is not used often, but it is quite useful when the need arises. redo redoes the current loop without modifying the control variable.
1.4.4 Labeled blocks
Occasionally, you will need to break out of a loop that is nested inside one or more other loops. For this reason, Perl provides a labeled block. When last is used with a label, control flows to the first statement beyond the labeled block.
OUT: for ( $i = 0; $i < 5; $i = $i + 1) { for ( $j = 0; $j < 5; $j = $j + 1) { if ($j == $i) { last OUT; } } } print "first statement after loops\n";
You can also use labels in connection with next or redo. With next, control flows to the next iteration of the labeled block. With redo, the loop of the labeled block is redone.