Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re: Why is the execution order of subexpressions undefined?

by Zaxo (Archbishop)
on Apr 12, 2005 at 05:03 UTC ( [id://446844]=note: print w/replies, xml ) Need Help??


in reply to Why is the execution order of subexpressions undefined?

Perl somehow knows what the execution order should be!

$ perl -MO=Concise,-exec -e'sub func {@_} my $rv = func( $i, ++$i, $i+ +2 )' 1 <0> enter 2 <;> nextstate(main 2 -e:1) v 3 <0> pushmark s 4 <$> gvsv(*i) s 5 <$> gvsv(*i) s 6 <1> preinc sKM/1 7 <$> gvsv(*i) s 8 <$> const(IV 2) s 9 <2> add[t2] sKM/2 a <$> gv(*func) s b <1> entersub[t3] sKS/TARG,1 c <0> padsv[$rv:2,3] sRM*/LVINTRO d <2> sassign vKS/2 e <@> leave[1 ref] vKP/REFC -e syntax OK $

Perl does make some guarantees about execution order - they are implied by the rules of precedence and associativity in perlop. In your example, the parens around the argument list make it a TERM, the highest precedence, so the enclosed expression is evaluated first. Within that expression, the preincrement operator has highest precedence, so it is applied next. Then comes addition in the third term and finally the commas. The commas tie in precedence, so associativity comes into it and they evaluate left to right - a trivial operation in this case. I think that func acts as a list operator, so assignment is evaluated next. Being right associative, assignment evaluates func first with the arguments we already calculated, and copies the result into $rv (in scalar context).

As far as I know, Perl doesn't make the distinction between operator-comma and punctuation-comma that C and C++ do. I believe that comma is always an operator in Perl (if I'm mistaken, I expect I'll hear about it!). It seems to be only scalar vs. list context which distinguishes between the sequence operator and list seperators - giving func the ($) prototype results in the same order of operations exposed by B::Concise.

Where C's undefinedness does creep in is through the increment and decrement operators. They are "nonassoc" in the precedence table, and are explicitly documented to have undefined results when used multiple times on the same variable in a single statement. It also seems to be discouraged to evaluate the variable itself, as in your example.

Currently, Perl permits those undefined operations and does them consistently, though oddly. Such expressions turn up pretty regularly in SoPW. Their behavior can be understood by realizing that post-inc and -dec return values while pre-inc and -dec return aliases (so reflect changes from subsequent operations), and that the operators are evaluated from left to right. Again, I emphasize that Perl docs warn against relying on this.

The precedence table approach to deciphering what perl will do is not perfect. For instance, being punctuation, brackets for array indexing or referencing are not covered in the table (though they obviously have a high effective precedence). I wonder if they come in under the TERM heading?

After Compline,
Zaxo

Replies are listed 'Best First'.
Re^2: Why is the execution order of subexpressions undefined? (victim)
by tye (Sage) on Apr 12, 2005 at 05:12 UTC

    I think you've fallen victim to the temptation that I posted about. I don't believe that Perl defines the order of evaluation of expressions based on the precedence table. That determines what the results will be but need not restrict Perl to arriving at the proscribed value in the exact order that you appear to have defined based on how Perl has so far been implemented.

    It would be sad if Perl 6 were not free to optimize

    my $x = $z * ( $y + 1 ) + $w / ( $y + 1 );

    By noting that $y + 1 is used twice and therefore could be computed beforehand and the result just used twice rather than computing it twice. But if you tie Perl's hand by saying that execution order is defined for such things, then Perl 6 will have no choice but to not optimize expressions, thwarting part of what was advertised as a big motivation for Parrot: the ability to optimize bytecode.

    - tye        

      Under an "as-if" rule, a bytecode optimizer need not obey the precedence rules, but the initial interpretation of your source must. Precedence and associativity are there to ensure that the expression you write is the one that gets calculated.

      After Compline,
      Zaxo

        We are talking order. The order that the calculations get performed need not be as you specified (based solely on precedence and associativity). Even if + might be redefined by the programmer such that x+y != y+x, computing x+y does not require that x be computed before y.

        - tye        

      It would be sad if Perl 6 were not free to optimize
       my $x = $z * ( $y + 1 ) + $w / ( $y + 1 );

      Why would defining execution order affect that optimisation?

      That just common subexpression elimination--clearly defined by the parens. The only sane defined ordering would be to execute the contents of parens first?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco.
      Rule 1 has a caveat! -- Who broke the cabal?

        I'd be insane to calculate $z first?

        So which is the defined order that you find so easy to come up with? You can only have one.

        - tye        

Re^2: Why is the execution order of subexpressions undefined?
by Anonymous Monk on Apr 12, 2005 at 13:22 UTC
    Perl somehow knows what the execution order should be!
    Eh, no. That's perl that knows, for a particular version of perl. The fact that it isn't defined in the language may mean that a next version may do it differently.
    they are implied by the rules of precedence and associativity in perlop.
    Eh, no. The rules of precedence and associativity only deal with parsing the language. They do not imply order of evaluation. The rules of precedence say that value of the expression:
    E1 + E2 * E3
    is calculated by multiplying the result of E2 and E3, and adding that to E1. It doesn't say E2 needs to be evaluated before E1 or E3. And indeed, current perl doesn't. In fact, it will evaluate E1, E2 and E3 in the same order as:
    E1 * E2 + E3
    even if the precedence of + and * are different.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://446844]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-19 21:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found