This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
 author Zefram Fri, 7 Feb 2020 09:30:21 +0000 (09:30 +0000) committer Karl Williamson Fri, 13 Mar 2020 04:34:26 +0000 (22:34 -0600)
 pod/perlop.pod patch | blob | blame | history

index 79e7bd9..9dc9278 100644 (file)
@@ -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) { ...
+
+
+    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">.