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

Hi, I'm new to the perl language, and I've run across a confusing result. Given the following (very obscure) snippet of code:
#!/usr/bin/perl $a = 10; $a = ($a+=5)+($a-=10); print "\n$a";
If you evaluate the right set of parens first, you should get 5.
If you evaluate the left set first, you should get 20.
If you eval both simultaneously, you should get 15.

Every time I run this, I get 10. What's the deal?

Replies are listed 'Best First'.
Re: precedence question
by Zaxo (Archbishop) on Aug 09, 2002 at 20:44 UTC

    The left term is executed first, then the right, since the + operator is left-associative. (Precedence doesn't enter because you have parenthesized to override precedence.) The trick is that mutators like += and ++ return not the current value of the operand, but an alias to the operand. The alias is not evaluated until called for in the next operation up the parse tree. Your code is equivalent to:

    $c = 10; $c += 5; $c -= 10; $c = $c + $c;
    ( I've changed the name to protect the innocent sort.)

    Arguably, this behavior breaks the precedence and associativity rules of Perl, but opponents of changing it point out that perlop promises behavior like C for these operators. In C, the order of evaluation for function arguments is explicitly not guaranteed, and operators are defined as functions of their arguments. Perl does make such a guarantee, so IMO the present implementation of mutators breaks some higher level promises than those of perlop. If mutators returned a value rather than an alias, your code would indeed set $a to 20.

    After Compline,
    Zaxo

      I see. Makes sense now; thanks!
Re: precedence question
by jynx (Priest) on Aug 09, 2002 at 20:47 UTC

    Perhaps this has to do with modifying a variable twice (or more) in the same line. There's are long discussions about the peril of such things here and there about the site...

    jynx

    PS d'oh, Zaxo beat me to the point...

Re: precedence question
by waswas-fng (Curate) on Aug 09, 2002 at 19:55 UTC
    try:
    #!/usr/bin/perl $a = 10; $a+=5;$a-=10; print "\n$a";
    or
    #!/usr/bin/perl $a = 10; $a = $a + 5 - 10; print "\n$a";
    The += and -= are shortcuts that set the lefthand.. the $a = is not needed.

    -Waswas
    Edited because I was speaking jibberish at the bottom (heh, talking on the phone while typing =)
      First of all, sorry about the additional post; refreshing the page on my browser had that unfortunate side effect. However, disregarding where I put the result, suppose I changed it to :
      #!/usr/bin/perl $a = 10; $result = ($a+=5) + ($a-=10); print "$result";
      My question is, since the assignment is made to the scalar variable $a using += and -= at supposedly different times, which parentheses is evaluated first? Or are they evaluated at the same time? I know there are different ways to do this; this is a kind of "What is the philosophy of Perl on this situation?" type of question, because I was curious. The possible answers I can see are:
      1: parenthesis right to left: (0+5)+(10-10) = 5.
      2: parenthesis left to right: (10+5)+(15-10) = 20.
      3: parenthesis simultaneously: (10+5)+(10-10) = 15.
      However, when this is run, with the modifications above, I still get 10 as an answer.
        Take this example:
        $a = 30; $one = ($a += 5) + ($a -= 10); print "a=$a one= $one \n";
        Output: a=25 one=50 it looks the the += is being updated after the calculation: so (30) + (30 - 10) = 50 then after the line passes you see $a is 25. Not sure if this is how it should work or not seems kinda fishy that the += is not proccessed the same way -= is. but i still don't understand what you are trying to add up here? $result = ($a+=5) + ($a-=10); is not very intuitive. Do you expect $result to be the result status of the += or -=? I am not sure what I would even expect $result to hold += and -= are not really normal arithmatic operators...

        -Waswas