summaryrefslogtreecommitdiff
path: root/pod/perlop.pod
diff options
context:
space:
mode:
authorZefram <zefram@fysh.org>2020-02-07 09:30:21 +0000
committerKarl Williamson <khw@cpan.org>2020-03-12 22:34:26 -0600
commite8a86671097b355fe5e0d9da2473a926929d87c4 (patch)
treeca8fcf1e356b0b038b5ff48ffb679a7105840f62 /pod/perlop.pod
parent02b85d3dab092d678cfc958a2dc252405333ed25 (diff)
downloadperl-e8a86671097b355fe5e0d9da2473a926929d87c4.tar.gz
pod/perlop.pod: expand doc on chained comparisons
Diffstat (limited to 'pod/perlop.pod')
-rw-r--r--pod/perlop.pod61
1 files changed, 47 insertions, 14 deletions
diff --git a/pod/perlop.pod b/pod/perlop.pod
index 79e7bd9fe3..9dc927804f 100644
--- a/pod/perlop.pod
+++ b/pod/perlop.pod
@@ -36,7 +36,8 @@ C<(2 + 4) * 5>. So the expression yields C<2 + 20 == 22>, rather than
C<6 * 5 == 30>.
I<Operator associativity> defines what happens if a sequence of the same
-operators is used one after another: whether they will be grouped at the left
+operators is used one after another:
+usually that they will be grouped at the left
or the right. For example, in C<9 - 3 - 2>, subtraction is left associative,
so C<9 - 3> is grouped together as the left-hand operand of the second
subtraction, rather than C<3 - 2> being grouped together as the right-hand
@@ -59,6 +60,47 @@ special evaluation rules that can result in an operand not being evaluated at
all; in general, the top-level operator in an expression has control of
operand evaluation.
+Some comparison operators, as their associativity, I<chain> with others
+of the same precedence. This means that each comparison is performed
+on the two arguments surrounding it, with each interior argument taking
+part in two comparisons, and the comparison results are implicitly ANDed.
+Thus S<C<"$a E<lt> $b E<lt>= $c">> behaves exactly like S<C<"$a E<lt>
+$b && $b E<lt>= $c">>, assuming that C<"$b"> is as simple a scalar as
+it looks. The ANDing short-circuits just like C<"&&"> does, stopping
+the sequence of comparisons as soon as one yields false.
+
+In a chained comparison, each argument expression is evaluated at most
+once, even if it takes part in two comparisons. (It is not evaluated
+at all if the short-circuiting means that it's not required for any
+comparisons.) This matters if the computation of an interior argument
+is expensive or non-deterministic. For example,
+
+ if($a < expensive_sub() <= $c) { ...
+
+is not entirely like
+
+ if($a < expensive_sub() && expensive_sub() <= $c) { ...
+
+but instead closer to
+
+ my $tmp = expensive_sub();
+ if($a < $tmp && $tmp <= $c) { ...
+
+in that the subroutine is only called once. However, it's not exactly
+like this latter code either, because the chained comparison doesn't
+actually involve any temporary variable (named or otherwise): there is
+no assignment. This doesn't make much difference where the expression
+is a call to an ordinary subroutine, but matters more with an lvalue
+subroutine, or if the argument expression yields some unusual kind of
+scalar by other means. For example, if the argument expression yields
+a tied scalar, then the expression is evaluated to produce that scalar
+at most once, but the value of that scalar may be fetched up to twice,
+once for each comparison in which it is actually used.
+
+Some operators are instead non-associative, meaning that it is a syntax
+error to use a sequence of those operators of the same precedence.
+For example, S<C<"$a .. $b .. $c">> is an error.
+
Perl operators have the following associativity and precedence,
listed from highest precedence to lowest. Operators borrowed from
C keep the same precedence relationship with each other, even where
@@ -518,17 +560,8 @@ than or equal to the right argument.
X<< ge >>
A sequence of relational operators, such as S<C<"$a E<lt> $b E<lt>=
-$c">>, does not group in accordance with left or right associativity,
-which would produce the almost-useless result of using the truth-value
-result of one comparison as a comparand in another comparison. Instead
-the comparisons are I<chained>: each comparison is performed on the
-two arguments surrounding it, with each interior argument taking part
-in two comparisons, and the comparison results are implicitly ANDed.
-Thus S<C<"$a E<lt> $b E<lt>= $c">> behaves very much like S<C<"$a E<lt>
-$b && $b E<lt>= $c">>. The ANDing short-circuits just like C<"&&">
-does, stopping the sequence of comparisons as soon as one yields false.
-Each argument expression is evaluated at most once, even if it takes
-part in two comparisons.
+$c">>, performs chained comparisons, in the manner described above in
+the section L</"Operator Precedence and Associativity">.
=head2 Equality Operators
X<equality> X<equal> X<equals> X<operator, equality>
@@ -550,8 +583,8 @@ to the right argument.
X<ne>
A sequence of the above equality operators, such as S<C<"$a == $b ==
-$c">>, performs chained comparisons, in the same manner as described in
-the previous section for relational operators.
+$c">>, performs chained comparisons, in the manner described above in
+the section L</"Operator Precedence and Associativity">.
Binary C<< "<=>" >> returns -1, 0, or 1 depending on whether the left
argument is numerically less than, equal to, or greater than the right