A sequence of statements within a scope[1] is called a block. Sometimes the scope is the entire file, such as a required file or the file containing your main program. Sometimes the scope is a string being evaluated with eval. But generally, a block is surrounded by braces ({}). When we say scope, we mean any of these three. When we mean a block with braces, we'll use the term BLOCK.
[1]Scopes and namespaces are described in Chapter 2, "Bits and Pieces", in Section 4.5, "Names".
Compound statements are built out of expressions and BLOCKs. Expressions are built out of terms and operators. In our syntax descriptions, we'll use the word EXPR to indicate a place where you can use any scalar expression. To indicate an expression evaluated in list context, we'll say LIST.
The following statements may be used to control conditional and repeated execution of BLOCKs. (The LABEL portion is optional.)
Note that unlike in C and Java, these are defined in terms of BLOCKs, not statements. This means that the braces are required--no dangling statements allowed. If you want to write conditionals without braces there are several ways to do so. The following all do the same thing:if (EXPR) BLOCK if (EXPR) BLOCK else BLOCK if (EXPR) BLOCK elsif (EXPR) BLOCK ... if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK unless (EXPR) BLOCK unless (EXPR) BLOCK else BLOCK unless (EXPR) BLOCK elsif (EXPR) BLOCK ... unless (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK LABEL while (EXPR) BLOCK LABEL while (EXPR) BLOCK continue BLOCK LABEL until (EXPR) BLOCK LABEL until (EXPR) BLOCK continue BLOCK LABEL for (EXPR; EXPR; EXPR) BLOCK LABEL foreach (LIST) BLOCK LABEL foreach VAR (LIST) BLOCK LABEL foreach VAR (LIST) BLOCK continue BLOCK LABEL BLOCK LABEL BLOCK continue BLOCK
Under most circumstances, we tend to prefer the last pair. These forms come with less eye-clutter than the others, especially the "or die" version. With the || form you need to get used to using parentheses religiously, but with the or version, it doesn't matter if you forget.unless (open(FOO, $foo)) { die "Can't open $foo: $!" } if (!open(FOO, $foo)) { die "Can't open $foo: $!" } die "Can't open $foo: $!" unless open(FOO, $foo); die "Can't open $foo: $!" if !open(FOO, $foo); open(FOO, $foo) || die "Can't open $foo: $!"; open FOO, $foo or die "Can't open $foo: $!";
But the main reason we like the last versions better is because of how they pull the important part of the statement right up to the front of the line where you'll see it first. The error handling is shoved off to the side so that you don't have to pay attention to it unless you want to.[2] If you tab all your "or die" checks over to the same column on the right each time, it's even easier to read:
chdir $dir or die "chdir $dir: $!"; open FOO, $file or die "open $file: $!"; @lines = <FOO> or die "$file is empty?"; close FOO or die "close $file: $!";
[2] (Like this footnote.)
Copyright © 2002 O'Reilly & Associates. All rights reserved.