=head2 Statement Modifiers
X<statement modifier> X<modifier> X<if> X<unless> X<while>
-X<until> X<foreach> X<for>
+X<until> X<when> X<foreach> X<for>
Any simple statement may optionally be followed by a I<SINGLE> modifier,
just before the terminating semicolon (or block ending). The possible
unless EXPR
while EXPR
until EXPR
+ when EXPR
+ for LIST
foreach LIST
The C<EXPR> following the modifier is referred to as the "condition".
print "Basset hounds got long ears" if length $ear >= 10;
go_outside() and play() unless $is_raining;
+C<when> executes the statement I<when> C<$_> smart matches C<EXPR>, and
+then either C<break>s out if it's enclosed in a C<given> scope or skips
+to the C<next> element when it lies directly inside a C<for> loop.
+See also L</"Switch statements">.
+
+ given ($something) {
+ $abc = 1 when /^abc/;
+ $just_a = 1 when /^a/;
+ $other = 1;
+ }
+
+ for (@names) {
+ admin($_) when [ qw/Alice Bob/ ];
+ regular($_) when [ qw/Chris David Ellen/ ];
+ }
+
The C<foreach> modifier is an iterator: it executes the statement once
for each item in the LIST (with C<$_> aliased to each item in turn).
the sense of the test is reversed.
The C<while> statement executes the block as long as the expression is
-true (does not evaluate to the null string C<""> or C<0> or C<"0">).
+L<true|/"Truth and Falsehood">.
The C<until> statement executes the block as long as the expression is
false.
The LABEL is optional, and if present, consists of an identifier followed
}}
This is caused by the fact that a block by itself acts as a loop that
-executes once, see L<"Basic BLOCKs and Switch Statements">.
+executes once, see L<"Basic BLOCKs">.
The form C<while/if BLOCK BLOCK>, available in Perl 4, is no longer
available. Replace any occurrence of C<if BLOCK> by C<if (do BLOCK)>.
C<do{}> blocks, which do I<NOT> count as loops.) The C<continue>
block is optional.
-The BLOCK construct can be used to emulate case
-structures.
+The BLOCK construct can be used to emulate case structures.
SWITCH: {
if (/^abc/) { $abc = 1; last SWITCH; }
Such constructs are quite frequently used, because older versions
of Perl had no official C<switch> statement.
-
=head2 Switch statements
X<switch> X<case> X<given> X<when> X<default>
-Starting from Perl 5.10, you can say
+Starting from Perl 5.10, you can say
- use feature "switch";
+ use feature "switch";
which enables a switch feature that is closely based on the
Perl 6 proposal.
to C<switch> and C<case> in other languages, so the code
above could be written as
- given($_) {
- when (/^abc/) { $abc = 1; }
- when (/^def/) { $def = 1; }
- when (/^xyz/) { $xyz = 1; }
- default { $nothing = 1; }
+ given($_) {
+ when (/^abc/) { $abc = 1; }
+ when (/^def/) { $def = 1; }
+ when (/^xyz/) { $xyz = 1; }
+ default { $nothing = 1; }
}
This construct is very flexible and powerful. For example:
- given() {
-
- xxxx
+ use feature ":5.10";
+ given($foo) {
+ when (undef) {
+ say '$foo is undefined';
+ }
+ when ("foo") {
+ say '$foo is the string "foo"';
+ }
+ when ([1,3,5,7,9]) {
+ say '$foo is an odd digit';
+ continue; # Fall through
+ }
+ when ($_ < 100) {
+ say '$foo is numerically less than 100';
+ }
+ when (\&complicated_check) {
+ say 'a complicated check for $foo is true';
+ }
+ default {
+ die q(I don't know what to do with $foo);
+ }
}
-Most of its power comes from the implicit smart matching:
+C<given(EXPR)> will assign the value of EXPR to C<$_>
+within the lexical scope of the block, so it's similar to
+
+ do { my $_ = EXPR; ... }
- when($foo) ...
+except that the block is automatically broken out of by a
+successful C<when> or an explicit C<break>.
+
+Most of the power comes from implicit smart matching:
+
+ when($foo)
is exactly equivalent to
- when($_ ~~ $foo) ...
+ when($_ ~~ $foo)
-(though you need to enable the "~~" feature before you
-can use the C<~~> operator directly). In fact C<when(EXPR)>
-is treated as an implicit smart match most of the time. The
-exceptions are that when EXPR is:
+In fact C<when(EXPR)> is treated as an implicit smart match most of the
+time. The exceptions are that when EXPR is:
=over 4
-=item o
+=item *
a subroutine or method call
-=item o
+=item *
a regular expression match, i.e. C</REGEX/> or C<$foo =~ /REGEX/>,
-or a negated regular expression match C<$foo !~ /REGEX/>.
+or a negated regular expression match (C<!/REGEX/> or C<$foo !~ /REGEX/>).
-=item o
+=item *
-a comparison (such as C<$_ E<lt> 10> or C<$x gt "abc">
+a comparison such as C<$_ E<lt> 10> or C<$x eq "abc">
+(or of course C<$_ ~~ $c>)
-=item o
+=item *
C<defined(...)>, C<exists(...)>, or C<eof(...)>
-=item o
+=item *
-A negated expression C<!(...)> or C<not (...)>, or a logical
+a negated expression C<!(...)> or C<not (...)>, or a logical
exclusive-or C<(...) xor (...)>.
+=item *
+
+a filetest operator, with the exception of C<-s>, C<-M>, C<-A>, and C<-C>,
+that return numerical values, not boolean ones.
+
+=item *
+
+the C<..> and C<...> flip-flop operators.
+
=back
-then the value of EXPR is used directly as a boolean.
+In those cases the value of EXPR is used directly as a boolean.
+
Furthermore:
=over 4
-=item o
+=item *
If EXPR is C<... && ...> or C<... and ...>, the test
is applied recursively to both arguments. If I<both>
arguments pass the test, then the argument is treated
as boolean.
-=item o
+=item *
-If EXPR is C<... || ...> or C<... or ...>, the test
+If EXPR is C<... || ...>, C<... // ...> or C<... or ...>, the test
is applied recursively to the first argument.
=back
These rules look complicated, but usually they will do what
you want. For example you could write:
- when (/^\d$/ && $_ < 75) { ... }
+ when (/^\d+$/ && $_ < 75) { ... }
+
+Another useful shortcut is that, if you use a literal array
+or hash as the argument to C<when>, it is turned into a
+reference. So C<given(@foo)> is the same as C<given(\@foo)>,
+for example.
C<default> behaves exactly like C<when(1 == 1)>, which is
to say that it always matches.
See L</"Smart matching in detail"> for more information
on smart matching.
+=head3 Breaking out
+
+You can use the C<break> keyword to break out of the enclosing
+C<given> block. Every C<when> block is implicitly ended with
+a C<break>.
+
=head3 Fall-through
You can use the C<continue> keyword to fall through from one
case to the next:
- given($foo) {
- when (/x/) { print "\$foo contains an 'x'\n"; continue }
- when (/y/) { print "\$foo contains a 'y'\n" }
- default { print "\$foo contains neither an 'x' nor a 'y' }
- }
+ given($foo) {
+ when (/x/) { say '$foo contains an x'; continue }
+ when (/y/) { say '$foo contains a y' }
+ default { say '$foo does not contain a y' }
+ }
=head3 Switching in a loop
For example, here's one way to count how many times a particular
string occurs in an array:
- my $count = 0;
- for (@array) {
- when ("foo") { ++$count }
+ my $count = 0;
+ for (@array) {
+ when ("foo") { ++$count }
}
- print "\@array contains $count copies of 'foo'\n";
+ print "\@array contains $count copies of 'foo'\n";
On exit from the C<when> block, there is an implicit C<next>.
You can override that with an explicit C<last> if you're only
=head3 Smart matching in detail
-
+The behaviour of a smart match depends on what type of thing its arguments
+are. The behaviour is determined by the following table: the first row
+that applies determines the match behaviour (which is thus mostly
+determined by the type of the right operand). Note that the smart match
+implicitly dereferences any non-blessed hash or array ref, so the "Hash"
+and "Array" entries apply in those cases. (For blessed references, the
+"Object" entries apply.)
+
+ $a $b Type of Match Implied Matching Code
+ ====== ===== ===================== =============
+ Any undef undefined !defined $a
+
+ Any Object invokes ~~ overloading on $object, or dies
+
+ Hash CodeRef sub truth for each key[1] !grep { !$b->($_) } keys %$a
+ Array CodeRef sub truth for each elt[1] !grep { !$b->($_) } @$a
+ Any CodeRef scalar sub truth $b->($a)
+
+ Hash Hash hash keys identical (every key is found in both hashes)
+ Array Hash hash slice existence grep { exists $b->{$_} } @$a
+ Regex Hash hash key grep grep /$a/, keys %$b
+ undef Hash always false (undef can't be a key)
+ Any Hash hash entry existence exists $b->{$a}
+
+ Hash Array hash slice existence grep { exists $a->{$_} } @$b
+ Array Array arrays are comparable[2]
+ Regex Array array grep grep /$a/, @$b
+ undef Array array contains undef grep !defined, @$b
+ Any Array match against an array element[3]
+ grep $a ~~ $_, @$b
+
+ Hash Regex hash key grep grep /$b/, keys %$a
+ Array Regex array grep grep /$b/, @$a
+ Any Regex pattern match $a =~ /$b/
+
+ Object Any invokes ~~ overloading on $object, or falls back:
+ Any Num numeric equality $a == $b
+ Num numish[4] numeric equality $a == $b
+ Any Any string equality $a eq $b
+
+ 1 - empty hashes or arrays will match.
+ 2 - that is, each element smart-matches the element of same index in the
+ other array. [3]
+ 3 - If a circular reference is found, we fall back to referential equality.
+ 4 - either a real number, or a string that looks like a number
+
+The "matching code" doesn't represent the I<real> matching code,
+of course: it's just there to explain the intended meaning. Unlike
+C<grep>, the smart match operator will short-circuit whenever it can.
=head3 Custom matching via overloading
You can change the way that an object is matched by overloading
-the C<'~~'> operator. This trumps the usual smart match semantics.
+the C<~~> operator. This trumps the usual smart match semantics.
+See L<overload>.
+
+It should be noted that C<~~> will refuse to work on objects that
+don't overload it (in order to avoid relying on the object's
+underlying structure).
+
+=head3 Differences from Perl 6
+
+The Perl 5 smart match and C<given>/C<when> constructs are not
+absolutely identical to their Perl 6 analogues. The most visible
+difference is that, in Perl 5, parentheses are required around
+the argument to C<given()> and C<when()> (except when this last
+one is used as a statement modifier). Parentheses in Perl 6
+are always optional in a control construct such as C<if()>,
+C<while()>, or C<when()>; they can't be made optional in Perl
+5 without a great deal of potential confusion, because Perl 5
+would parse the expression
+
+ given $foo {
+ ...
+ }
+
+as though the argument to C<given> were an element of the hash
+C<%foo>, interpreting the braces as hash-element syntax.
+
+The table of smart matches is not identical to that proposed by the
+Perl 6 specification, mainly due to the differences between Perl 6's
+and Perl 5's data models.
+
+In Perl 6, C<when()> will always do an implicit smart match
+with its argument, whilst it is convenient in Perl 5 to
+suppress this implicit smart match in certain situations,
+as documented above. (The difference is largely because Perl 5
+does not, even internally, have a boolean type.)
=head2 Goto
X<goto>