Getting out of nested loops

Nested loops make code less readable, so it is usually better avoid them in the first place. On the other side, sometimes they are the most natural solution to a problem, so not using them make the code less clear.

One problem that we could face when we write nested loop is that is not easy to completely get out from it when we are in an internal loop. There are to classical ways to achieve this result: using flag variables, that make the code clumsy; using goto instructions, that make the code a mess.

Perl offer a third way, using a label loop - that actually let us use a sort of domesticated goto mechanism.

The problem that we want to solve is this: we want to loop indefinitely on the input provided by the user, stopping only when one of a list of magic words is provided.

The natural way of implementing a solution is having a loop on STDIN, and then an internal loop for checking the user input against the list of terminators.

The issue is: what should be do when we find that the user input a terminator? We should get out of the external loop, obviously, but how we could achieve it. We have a keyword, last, that is used to step out a loop, but it works only for the current loop.

The solution is marking with a label the external loop (traditionally labels are written all-upperacase) and specifying the loop we want to step out with the last statement:

my @terminator = qw(quit exit stop);

LOOP: while(<>) {
chomp;
for my $check (@terminator) {
last LOOP if $check eq $_;
}
print "---> $_\n";
}
print "Done.\n";

If we used last without specifying the LOOP label, the result would have been disappointing. No way of getting out of the while, we would have been trapped forever (or till an interrupt occurred) in the loop.

Chapter 4 of Beginning Perl by Simon Cozens is about loops and decisions.

No comments:

Post a Comment