=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 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:
+Most of the time, C<when(EXPR)> is treated as an implicit smart match of
+C<$_>, i.e. C<$_ ~~ EXPR>. (See L</"Smart matching in detail"> for more
+information on smart matching.) But when EXPR is one of the below
+exceptional cases, it is used directly as a boolean:
=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<given>, 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
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' }
+ 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
=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.)
+
+Note that the "Matching Code" column is not always an exact rendition. For
+example, the smart match operator short-circuits whenever possible, but
+C<grep> does not.
+
+ $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
+ undef Any undefined !defined($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
=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 may alter the usual smart match semantics.
+
+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).
+
+Note also that smart match's matching rules take precedence over
+overloading, so if C<$obj> has smart match overloading, then
+
+ $obj ~~ X
+
+will not automatically invoke the overload method with X as an argument;
+instead the table above is consulted as normal, and based in the type of X,
+overloading may or may not be invoked.
+
+See L<overload>.
+
+=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>