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
(see below). 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 elsif
s, 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.)