Compound statements
In perl, a sequence of commands may
be treated as one command by enclosing it in curly brackets. We
will call this a BLOCK.
The following compound commands may be used
to control flow:
if (EXPR) BLOCK
if (EXPR) BLOCK else BLOCK
if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
LABEL while (EXPR) BLOCK
LABEL while (EXPR) BLOCK continue BLOCK
LABEL for (EXPR; EXPR; EXPR) BLOCK
LABEL foreach VAR (ARRAY) BLOCK
LABEL BLOCK continue BLOCK
Note that, unlike C and Pascal, these are
defined in terms of BLOCKs, not statements. This means that the
curly brackets are required--no dangling statements
allowed. If you want to write conditionals without curly brackets
there are several other ways to do it. The following all do the
same thing:
if (!open(foo)) { die "Can't open $foo: $!"; }
die "Can't open $foo: $!" unless open(foo);
open(foo) || die "Can't open $foo: $!"; # foo or bust!
open(foo) ? 'hi mom' : die "Can't open $foo: $!";
# a bit exotic, that last one
The if statement is straightforward. Since BLOCKs are
always bounded by curly brackets, there is never any ambiguity
about which if an else goes with. If you use unless
in place of if, the sense of the test is reversed.
The while statement
executes the block as long as the expression is true (does not
evaluate to the null string or 0). The LABEL is optional, and if
present, consists of an identifier followed by a colon. The LABEL
identifies the loop for the loop control statements next, last, and redo. If there is a continue BLOCK,
it is always executed just before the conditional is about to be
evaluated again, similarly to the third part of a for loop
in C. Thus it can be used to increment a loop variable, even when
the loop has been continued via the next statement (similar
to the C "continue" statement).
If the word while is replaced by the
word until, the sense of the test is reversed, but the
conditional is still tested before the first iteration.
In either the if or the while
statement, you may replace "(EXPR)" with a BLOCK, and
the conditional is true if the value of the last command in that
block is true.
The for loop works exactly like the corresponding while
loop:
for ($i = 1; $i < 10; $i++) {
...
}
is the same as
$i = 1;
while ($i < 10) {
...
} continue {
$i++;
}
The foreach loop iterates
over a normal array value and sets the variable VAR to be each
element of the array in turn. The variable is implicitly local to
the loop, and regains its former value upon exiting the loop. The
"foreach" keyword is actually identical to the "for"
keyword, so you can use "foreach" for readability or
"for" for brevity. If VAR is omitted, $_ is set to each value. If ARRAY is an actual array (as
opposed to an expression returning an array value), you can
modify each element of the array by modifying VAR inside the loop.
Examples:
for (@ary) { s/foo/bar/; }
foreach $elem (@elements) {
$elem *= 2;
}
for ((10,9,8,7,6,5,4,3,2,1,'BOOM')) {
print $_, "\n"; sleep(1);
}
for (1..15) { print "Merry Christmas\n"; }
foreach $item (split(/:[\\\n:]*/, $ENV{'TERMCAP'})) {
print "Item: $item\n";
}
The BLOCK by itself (labeled or not) is
equivalent to a loop that executes once. Thus you can use any of
the loop control statements in it to leave or restart the block.
The continue block is optional. This construct is
particularly nice for doing case structures.
foo: {
if (/^abc/) { $abc = 1; last foo; }
if (/^def/) { $def = 1; last foo; }
if (/^xyz/) { $xyz = 1; last foo; }
$nothing = 1;
}
There is no official switch statement in
perl, because there are already several ways to write the
equivalent. In addition to the above, you could write
foo: {
$abc = 1, last foo if /^abc/;
$def = 1, last foo if /^def/;
$xyz = 1, last foo if /^xyz/;
$nothing = 1;
}
or
foo: {
/^abc/ && do { $abc = 1; last foo; };
/^def/ && do { $def = 1; last foo; };
/^xyz/ && do { $xyz = 1; last foo; };
$nothing = 1;
}
or
foo: {
/^abc/ && ($abc = 1, last foo);
/^def/ && ($def = 1, last foo);
/^xyz/ && ($xyz = 1, last foo);
$nothing = 1;
}
or even
if (/^abc/)
{ $abc = 1; }
elsif (/^def/)
{ $def = 1; }
elsif (/^xyz/)
{ $xyz = 1; }
else
{$nothing = 1;}
As it happens, these are all optimized
internally to a switch structure, so perl jumps directly to the
desired statement, and you needn't worry about perl executing a
lot of unnecessary statements when you have a string of 50
elsifs, as long as you are testing the same simple scalar
variable using ==, eq, or pattern matching as above. (If you're
curious as to whether the optimizer has done this for a
particular case statement, you can use the -D1024 switch to list
the syntax tree before execution.)
|