Compound statements in PERL
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 and 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.)
Click here to go back to the Perl index
|