Last Updated:

Loop control commands | Perl

Loop control commands

Each cycle in the program ends when some condition determined by the operator himself is reached. In the while and for loops, this is due to the falsity of the condition expression, and in the foreach loop with the end of the search of all list items. Sometimes there is a need, when some conditions arise, to complete the execution of the entire loop, or to interrupt the execution of loop statements and move on to the next iteration. For such purposes, the Perl language provides three lastnext and redo commands, which are called loop control commands.

The syntax of these commands is simple – a keyword that can be followed by an optional label IDENTIFIER:

last TAG ID;
next TAG ID;
redo TAG ID;

The semantics of these commands are also simple. They change the default order of execution of loops in the language and pass control to a specific location in the program, ending the execution of the loop (last), moving to the next iteration of the loop (next), or repeating the execution of the operators of the loop body at the same values of the loop variables (redo). The transition location is specified by a label. Remember the syntax of loop statements? Each of them can be tagged. It is the label IDs of loop operators that are used in control commands to specify where control is transferred.

The label in Perl is specified by an identifier followed by a colon. Loop management commands use the label ID, not the label.

A few words about terminology. The reader probably noticed that we do not call loop control commands operators. And rightly so. They are not operators, although they can be used as operators. They should be considered unary operations, the result of which is a change in the sequence of execution of operators. Therefore, loop control commands can be used in any Perl expression. Note that they should be used in expressions where it makes sense to use them, such as comma-operated expressions:

open(INPUT_FILE, $file)
or warn ("Cannot open $file: $!\n"),
next FILE;

This statement can be part of a program that sequentially opens and processes files in a loop. The next command initiates another iteration of the loop labeled FILE if the file cannot be opened in the current iteration. Note that it is used as the operand of the comma operation. In this context, this command makes sense. The following statement is syntactically correct, but using the redo command in it makes no sense:

print "qu-qu", 5 * redo OUT, "hi-hi\n";

The result of executing this statement is to repeat the calculations of the loop statements labeled WITH THE ODT label, that is, to simply execute the redo OUT command.

Regarding loop control commands, it should be said that modifiers can be applied to them, since they are considered as simple operators used independently with a semicolon:

next if $a – 2;

Switching to the next iteration of the loop will only occur if the variable $a is 2.

Last Team

The last command immediately stops executing the loop in which it is defined and passes control to the statement immediately following the loop statement. It is useful to use it to find one specific value in an array (Example 5.12).

#! perl – w
@letters = ("A".."Z");
for ($index=0; $index<01etters; $index++) {
last if $letters[$index] eq "M"; } print $index;

The loop in Example 5.12 will run until iteration of the elements in the $letters array reaches an element that contains an "m" character. After that, the first after the statement for the program operator will be executed. As a result, the number 12 will be printed - the index of the element containing the symbol "m".

The label is used to specify the transfer of control in the case of nested loops: control is passed directly to the operator following the loop operator with the specified label (Example 5.13).

CYCLE_1: while (…){, CYCLE_2: for (…) {
CYCLE_3: foreach(...) { last CYCLE_2; }
Loop statements CYCLE_2 }
CYCLE_1 loop statements
# Transfer control here
t statement last CYCLE_2; }

If you specify the label CYCLE_I in the last command, control will be transferred to the first program statement after the outermost cycle. If you specify a label CYCLE_S in the last command (or set it without a label at all), control will be passed to the first statement of the CYCLE_2 loop statement group.

The control of the last command is transferred not to the loop operator with the corresponding label, but to the operator immediately following it.

The last command exits the loop without executing any blocks of continue statements.

Next Command

The next command allows you to skip the statements located after it in the body of the loop and move on to the next iteration of the loop. If a loop statement contains a continue block, its statements are executed before checking the end-of-loop condition at which the next iteration begins. One application of this command is to process certain elements of an array without doing anything to others. Example 5.14 assigns an asterisk "*" to all elements of an array containing even numbers.

#! perl-w
@array = (2, 5, 8, 4, 7,, 9);
print "To: @array\n";
foreach (Sarray) { next if $_ % 2;
$_ = "*";
print "After: @array\n";

The output of Example 5.14 is shown below:

До: 2 5 8 4 7 9
После: * 5 * * 7 9

If the array element is an odd number, the result of the $_ % operation is i (True) and the next command initiates the next iteration of the foreach loop without changing the value of the current array element. If the value of an array element is an even number, the next command fails and the value of the element is changed to the "*" character.

The next command used with the label ID interrupts the execution of the loop in the body of which it resides and begins a new iteration of the loop with the specified label, having previously executed its continue block, if any (Example 5.15).

#! perl-w
OUT: while ($out < 2) {
print "Beginning of outer loop\n";
for($in=0; $in<=2; $in++) {
print "\$out: $out\t\$in: $in\n"; next OUT if $in =1; }
print "\$out: $out\n"; # Never executed! } continue {
print "Continue block of outer loop\n"; $out++; }

The output of this program will be as follows:

Beginning of outer loop
$out: 0 $in: 0
$out: 0 $in: 1
continue block of outer loop
Beginning of outer loop
$out: I $in: 0
$out: I $in: 1
continue block of outer loop

Note that the number of iterations of the inner for loop is two, because the second iteration of the inner for loop runs the next OUT command, which stops executing it and initializes the execution of the next iteration of the outer OUT loop. The print statement of this loop is skipped, the continue statement block is executed, the condition is checked, and if it is true, the loop body is executed. Therefore, the out outer loop print statement is not executed at any time, as evidenced by the output of Example 5.15.

Redo Team

The redo command reruns the loop body statements without initializing the next iteration. This means that neither the for loop change expression, nor the continue block operators, if present, nor the condition expression are evaluated. The loop body operators behind the redo operator are skipped and the loop body starts executing again with the values of the variables they had before this control transfer was performed. Example 5.16 demonstrates the use of the redo command.

I! perl-w $notempty= 0;
$total = 0;
for (;;) { tt Infinite loop
$line=<STDIN>; # Input string
last if $line eq "END"; # Exit loop
redo if $line eq ""; # Return to read line
++$notempty; }
print "Total lines read: $total\nM3 of them not empty: $notempty\n";

This program in an infinite loop waits for the user to enter a string of data on the keyboard and in the variable $ total counts the number of entered rows. The $notempty variable calculates the number of rows that are not empty. If an empty string is entered, the redo command starts re-executing the loop body statements without increasing the variable $notempty by one. To complete an infinite loop, enter the string END. In this case, the last command is executed.

The chop function is used to remove the line transition character "\n" from a user-entered string, so the program compares it to lines without a trailing line character (compares to example 5.7).

If the redo command is used with a label ID, its action is similar to that of the next command, with the only difference that it simply passes control to the first loop body operator with the specified label without initiating the next iteration or calculating the continue block statements. To illustrate this use of the redo command, let's rewrite the program of Example 5.16 as follows:

#! perl - w $notempty = 0; $total = 0; OUT: while (1) {
print "Enter lines\n"; # The command transfers control here redo OUT; for {;;) {
last OUT if-$line eq "END"; I Exit all cycles
redo OUT if $line eq "";
++$notempty; } } print "Total lines read: $tptal\nH3 not empty: $notempty\n";

In Example 5.17, we introduced an outer out loop and changed the redo and last commands to a label to an outer loop. Now, if the user enters an empty string, the redo OUT command passes control to the first statement of the outer loop, and the program prints a prompt to enter the strings.