summaryrefslogtreecommitdiff
path: root/pod/perlsyn.pod
diff options
context:
space:
mode:
authorZefram <zefram@fysh.org>2017-11-21 18:17:10 +0000
committerZefram <zefram@fysh.org>2017-11-21 18:17:10 +0000
commitb69ef0135bfebf0c32023bcb970dbb95957b32e7 (patch)
tree30b3226764fe880873e9d64bbb41200cc7aa5dd5 /pod/perlsyn.pod
parent76ed45178844dff782880573017d9b7c9fbc0007 (diff)
downloadperl-b69ef0135bfebf0c32023bcb970dbb95957b32e7.tar.gz
regularise "when"
Remove from "when" the implicit enreferencement of array/hash conditions and the implicit smartmatch of most conditions. Delete most of the documentation about behaviour of older versions of given/when, because explaining the now-old "when" behaviour would be excessively cumbersome and there's little compatibility to take advantage of. Delete the documentation about differences of given/when from the Perl 6 feature, because the differences are now even more extensive and it's too much difference to sensibly explain. Add tests of "when" in isolation.
Diffstat (limited to 'pod/perlsyn.pod')
-rw-r--r--pod/perlsyn.pod275
1 files changed, 12 insertions, 263 deletions
diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod
index 80eca0a275..d02516cab4 100644
--- a/pod/perlsyn.pod
+++ b/pod/perlsyn.pod
@@ -671,29 +671,18 @@ Or if you don't care to play it safe, like this:
default { $nothing = 1 }
}
-The arguments to C<given> and C<when> are in scalar context,
-and C<given> aliases the C<$_> variable to the result of evaluating its
+The arguments to C<given> and C<when> are in scalar context.
+C<given> aliases the C<$_> variable to the result of evaluating its
topic expression.
+C<when> evaluates its argument as a truth value. If the argument
+was false then it does not execute its block, and proceeds to the
+following statement. If the argument was true, it executes the block,
+then implicitly jumps to the end of the topicalizer.
-Exactly what the I<EXPR> argument to C<when> does is hard to describe
-precisely, but in general, it tries to guess what you want done. Sometimes
-it is interpreted as C<< $_ ~~ I<EXPR> >>, and sometimes it is not. It
-also behaves differently when lexically enclosed by a C<given> block than
-it does when dynamically enclosed by a C<foreach> loop. The rules are far
-too difficult to understand to be described here. See L</"Experimental Details
-on given and when"> later on.
-
-Due to an unfortunate bug in how C<given> was implemented between Perl 5.10
-and 5.16, under those implementations the version of C<$_> governed by
-C<given> is merely a lexically scoped copy of the original, not a
-dynamically scoped alias to the original, as it would be if it were a
-C<foreach> or under both the original and the current Perl 6 language
-specification. This bug was fixed in Perl 5.18 (and lexicalized C<$_> itself
-was removed in Perl 5.24).
-
-If your code still needs to run on older versions,
-stick to C<foreach> for your topicalizer and
-you will be less unhappy.
+On versions of Perl preceding Perl 5.28, C<given> and C<when> behave
+somewhat differently from their present behaviour.
+If your code needs to run on older versions,
+avoid C<given> and C<when>.
=head2 Goto
X<goto>
@@ -907,194 +896,10 @@ shell:
=head2 Experimental Details on given and when
As previously mentioned, the "switch" feature is considered highly
-experimental; it is subject to change with little notice. In particular,
-C<when> has tricky behaviours that are expected to change to become less
-tricky in the future. Do not rely upon its current (mis)implementation.
-Before Perl 5.28, C<given> also had tricky behaviours that you should still
+experimental; it is subject to change with little notice.
+Before Perl 5.28, C<given> and C<when> had tricky behaviours that you should
beware of if your code must run on older versions of Perl.
-Here is a longer example of C<given>:
-
- 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);
- }
- }
-
-Before Perl 5.18, C<given(EXPR)> assigned the value of I<EXPR> to
-merely a lexically scoped I<B<copy>> (!) of C<$_>, not a dynamically
-scoped alias the way C<foreach> does. That made it similar to
-
- do { my $_ = EXPR; ... }
-
-except that the block was automatically broken out of by a successful
-C<when> or an explicit C<break>. Because it was only a copy, and because
-it was only lexically scoped, not dynamically scoped, you could not do the
-things with it that you are used to in a C<foreach> loop. In particular,
-it did not work for arbitrary function calls if those functions might try
-to access $_. Best stick to C<foreach> for that.
-
-Before Perl 5.28, if the I<EXPR> in C<given(EXPR)> was an array or hash
-reference then the topic would be a reference to that array or hash,
-rather than the result of evaluating the array or hash in scalar context.
-
-Most of the power comes from the implicit smartmatching that can
-sometimes apply. Most of the time, C<when(EXPR)> is treated as an
-implicit smartmatch of C<$_>, that is, C<$_ ~~ EXPR>. (See
-L<perlop/"Smartmatch Operator"> for more information on smartmatching.)
-But when I<EXPR> is one of the 10 exceptional cases (or things like them)
-listed below, it is used directly as a boolean.
-
-=over 4
-
-=item Z<>1.
-
-A user-defined subroutine call or a method invocation.
-
-=item Z<>2.
-
-A regular expression match in the form of C</REGEX/>, C<$foo =~ /REGEX/>,
-or C<$foo =~ EXPR>. Also, a negated regular expression match in
-the form C<!/REGEX/>, C<$foo !~ /REGEX/>, or C<$foo !~ EXPR>.
-
-=item Z<>3.
-
-A smart match that uses an explicit C<~~> operator, such as C<EXPR ~~ EXPR>.
-
-B<NOTE:> You will often have to use C<$c ~~ $_> because the default case
-uses C<$_ ~~ $c> , which is frequentlythe opposite of what you want.
-
-=item Z<>4.
-
-A boolean comparison operator such as C<$_ E<lt> 10> or C<$x eq "abc">. The
-relational operators that this applies to are the six numeric comparisons
-(C<< < >>, C<< > >>, C<< <= >>, C<< >= >>, C<< == >>, and C<< != >>), and
-the six string comparisons (C<lt>, C<gt>, C<le>, C<ge>, C<eq>, and C<ne>).
-
-=item Z<>5.
-
-At least the three builtin functions C<defined(...)>, C<exists(...)>, and
-C<eof(...)>. We might someday add more of these later if we think of them.
-
-=item Z<>6.
-
-A negated expression, whether C<!(EXPR)> or C<not(EXPR)>, or a logical
-exclusive-or, C<(EXPR1) xor (EXPR2)>. The bitwise versions (C<~> and C<^>)
-are not included.
-
-=item Z<>7.
-
-A filetest operator, with exactly 4 exceptions: C<-s>, C<-M>, C<-A>, and
-C<-C>, as these return numerical values, not boolean ones. The C<-z>
-filetest operator is not included in the exception list.
-
-=item Z<>8.
-
-The C<..> and C<...> flip-flop operators. Note that the C<...> flip-flop
-operator is completely different from the C<...> elliptical statement
-just described.
-
-=back
-
-In those 8 cases above, the value of EXPR is used directly as a boolean, so
-no smartmatching is done. You may think of C<when> as a smartsmartmatch.
-
-Furthermore, Perl inspects the operands of logical operators to
-decide whether to use smartmatching for each one by applying the
-above test to the operands:
-
-=over 4
-
-=item Z<>9.
-
-If EXPR is C<EXPR1 && EXPR2> or C<EXPR1 and EXPR2>, the test is applied
-I<recursively> to both EXPR1 and EXPR2.
-Only if I<both> operands also pass the
-test, I<recursively>, will the expression be treated as boolean. Otherwise,
-smartmatching is used.
-
-=item Z<>10.
-
-If EXPR is C<EXPR1 || EXPR2>, C<EXPR1 // EXPR2>, or C<EXPR1 or EXPR2>, the
-test is applied I<recursively> to EXPR1 only (which might itself be a
-higher-precedence AND operator, for example, and thus subject to the
-previous rule), not to EXPR2. If EXPR1 is to use smartmatching, then EXPR2
-also does so, no matter what EXPR2 contains. But if EXPR2 does not get to
-use smartmatching, then the second argument will not be either. This is
-quite different from the C<&&> case just described, so be careful.
-
-=back
-
-These rules are complicated, but the goal is for them to do what you want
-(even if you don't quite understand why they are doing it). For example:
-
- when (/^\d+$/ && $_ < 75) { ... }
-
-will be treated as a boolean match because the rules say both
-a regex match and an explicit test on C<$_> will be treated
-as boolean.
-
-Also:
-
- when ([qw(foo bar)] && /baz/) { ... }
-
-will use smartmatching because only I<one> of the operands is a boolean:
-the other uses smartmatching, and that wins.
-
-Further:
-
- when ([qw(foo bar)] || /^baz/) { ... }
-
-will use smart matching (only the first operand is considered), whereas
-
- when (/^baz/ || [qw(foo bar)]) { ... }
-
-will test only the regex, which causes both operands to be
-treated as boolean. Watch out for this one, then, because an
-arrayref is always a true value, which makes it effectively
-redundant. Not a good idea.
-
-Tautologous boolean operators are still going to be optimized
-away. Don't be tempted to write
-
- when ("foo" or "bar") { ... }
-
-This will optimize down to C<"foo">, so C<"bar"> will never be considered (even
-though the rules say to use a smartmatch
-on C<"foo">). For an alternation like
-this, an array ref will work, because this will instigate smartmatching:
-
- when ([qw(foo bar)] { ... }
-
-This is somewhat equivalent to the C-style switch statement's fallthrough
-functionality (not to be confused with I<Perl's> fallthrough
-functionality--see below), wherein the same block is used for several
-C<case> statements.
-
-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.
-
=head3 Breaking out
You can use the C<break> keyword to break out of the enclosing
@@ -1183,60 +988,4 @@ interested in only the first match alone.
This doesn't work if you explicitly specify a loop variable, as
in C<for $item (@array)>. You have to use the default variable C<$_>.
-=head3 Differences from Perl 6
-
-The Perl 5 smartmatch and C<given>/C<when> constructs are not compatible
-with their Perl 6 analogues. The most visible difference and least
-important 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.
-
-However, their are many, many other differences. For example,
-this works in Perl 5:
-
- use v5.12;
- my @primary = ("red", "blue", "green");
-
- if (@primary ~~ "red") {
- say "primary smartmatches red";
- }
-
- if ("red" ~~ @primary) {
- say "red smartmatches primary";
- }
-
- say "that's all, folks!";
-
-But it doesn't work at all in Perl 6. Instead, you should
-use the (parallelizable) C<any> operator:
-
- if any(@primary) eq "red" {
- say "primary smartmatches red";
- }
-
- if "red" eq any(@primary) {
- say "red smartmatches primary";
- }
-
-The table of smartmatches in L<perlop/"Smartmatch Operator"> is not
-identical to that proposed by the Perl 6 specification, mainly due to
-differences between Perl 6's and Perl 5's data models, but also because
-the Perl 6 spec has changed since Perl 5 rushed into early adoption.
-
-In Perl 6, C<when()> will always do an implicit smartmatch with its
-argument, while in Perl 5 it is convenient (albeit potentially confusing) to
-suppress this implicit smartmatch in various rather loosely-defined
-situations, as roughly outlined above. (The difference is largely because
-Perl 5 does not have, even internally, a boolean type.)
-
=cut