http://www.perlmonks.org?node_id=1013066

muba has asked for the wisdom of the Perl Monks concerning the following question:

According to perldoc perlop, terms have the highest precedence of everything:

A TERM has the highest precedence in Perl. They include variables, quote and quote-like operators, any expression in parentheses ...

Please consider the following code.

use 5.010; sub apple { say "apple" } sub banana { say "banana" } sub cherry { say "cherry" } apple && (banana || cherry)

Given that expressions in parentheses have topmost priority, one would expect Perl to evaluate (banana || cherry) first, which would boil down to say "banana" which would return 1, and only then to evaluate apple && (1).

So the output I more or less expected is:

banana apple

However, the output I get is:

apple banana

Please shed some light on this. Why isn't the parenthesed expression evaluated first? I understand the short circuiting nature of the logical operators — for one, this explains why cherry isn't outputted at all, but I fail to understand how && seems to have higher precedence than ( EXPR ), despite the information in the documentation.

Replies are listed 'Best First'.
Re: Operator precedence
by BrowserUk (Patriarch) on Jan 12, 2013 at 23:13 UTC

    Apple is a term just as the parenthesized expression is, and therefore has equal precedence to it.

    But the operator && evaluates its left term before its right.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      So simple... and still I somehow overlooked it.

      Thanks a lot, BrowserUk!

        Not that it helps particularly with this particular expression, but the output from B::Deparse is often enlightening.

        I love the fact that perl turns that into a low precedence boolean operator used for flow control and a postfix if. P::C must get righteously apoplectic :)

        C:\test>perl -MO=Deparse,p use 5.010; sub apple { say "apple" } sub banana { say "banana" } sub cherry { say "cherry" } apple && (banana || cherry) ^Z sub BEGIN { require 5.01; } sub apple { no feature; use feature ':5.10'; say 'apple'; } sub banana { no feature; use feature ':5.10'; say 'banana'; } sub cherry { no feature; use feature ':5.10'; say 'cherry'; } no feature; use feature ':5.10'; banana or cherry if apple ; - syntax OK

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Operator precedence
by ikegami (Patriarch) on Jan 13, 2013 at 21:21 UTC

    There's no such thing as priority, and neither precedence nor associativity define the order in which stuff is evaluated. They determine what is an operand of what operator.

    apple && (banana || cherry) apple: LHS operand of && banana || cherry: RHS operand of && banana: LHS operand of || cherry: LHS operand of || (apple && banana) || cherry apple && banana: LHS operand of || apple: LHS operand of && banana: RHS operand of && cherry: RHS operand of ||

    Operand evaluation order is what controls the order in which stuff is evaluated.

    In order to provide short-circuiting, && evaluates its LHS operand before its RHS. Same goes for ||.

    Given

    apple && (banana || cherry) apple: LHS operand of && banana || cherry: RHS operand of && banana: LHS operand of || cherry: LHS operand of ||

    apple must be evaluated before banana || cherry
    banana must be evaluated before cherry

    So we get:

    1. apple
    2. banana
    3. cherry
    4. ||
    5. &&

    Given

    (apple && banana) || cherry apple && banana: LHS operand of || apple: LHS operand of && banana: RHS operand of && cherry: RHS operand of ||

    apple && banana must be evaluated before cherry
    apple must be evaluated before banana

    So we get:

    1. apple
    2. banana
    3. &&
    4. cherry
    5. ||

      It took me a good couple days to realise what you meant with "There's no such thing as priority, and neither precedence nor associativity define the order in which stuff is evaluated. They determine what is an operand of what operator."

      But I get it now. Looking at it that clarifies a lot. Thank you.

Re: Operator precedence
by sundialsvc4 (Abbot) on Jan 14, 2013 at 03:08 UTC

    These two operators exhibit what is called short-circuit evaluation.   If the left-hand side of && is found to be False, the right-hand side is not evaluated at all, since to do so would be pointless:   “False and anything-at-all is already known to be False.”   Likewise, if the left-hand side of || is found to be True, then the right-hand side is not evaluated since what it’s got is already sufficient:   “True or anything-at-all is already known to be True.”

    The computer had to evaluate apple to conclude if it was True or False.   (It was True.)   Since it was True, short-circuiting did not occur so it proceeded to its rightmost part.   But, having evaluated banana in the parenthesized expression (also True), that did short-circuit:   within that subexpression, it did not have to go further.   A call to cherry will never occur in this program fragment as-written.