<?php

$num1=3;
$num2=$num1 + ++$num1;
$num3=3;
$num4=$num3 + $num3 + ++$num3;

echo "$num1";//1st displayed value:4
echo "<br/>";
echo "$num2";//2nd displayed value:8
echo "<br/>";
echo "$num3";//3rd displayed value:4
echo "<br/>";
echo "$num4";//4th displayed value:10

/the second and fourth displayed values are not consistent with each other/

?>

The same thing in JavaScript:

<script>

var num3=3;
var num4=num3 + ++num3;
var num5=3;
var num6=num5 + num5 + ++num5;
var brk="<br/>";

document.write(num3+brk);//1st displayed value:4
document.write(num4+brk);//2nd displayed value:7
document.write(num5+brk);//3rd displayed value:4
document.write(num6+brk);//4th displayed value:10

/The second and fourth displayed values are consistent with each other/

</script>

    your results for javascript are correct.

    3+1 = 4 (++ increments the variable itself)
    3+4 = 7
    3+1 = 4 (again)
    3+3+4 = 10

    As for the php, not sure why its giving 8 for the second answer, but the other 3 are correct.

      Actually, the JS results are the ones that I did not expect.

      First, remember that there's a difference between [font=monospace]++$num[/font] and [font=monospace]$num++[/font]:

      <?php
      
      $x = 1;
      var_dump( $x++ );  // 1
      var_dump( $x );    // 2
      
      $y = 1;
      var_dump( ++$y );  // 2
      var_dump( $y );    // 2

      [font=monospace]++$num[/font] increments before evaluating the current statement, while [font=monospace]$num++[/font] increments after.

      Your statements are actually being evaluated like so:

      
      $num1 = 3;
      $num2 = $num1 + ++$num1;
      
      // ++$num1 is evaluated first:
      $num2 = 4     +   4;
      $num2 = 8;
      
      
      $num3 = 3;
      $num4 = $num3 + $num3 + ++$num3;
      
      // a little more complicated.  order of operations for addition is ltr.
      // $num3 + $num3 is evaluated first:
      $num4 = 3     + 3     + ++$num3;
      $num4 = 6             + ++$num3;
      
      // then, ++$num3 is evaluated:
      $num4 = 6             +   4;
      
      // then the final addition is done:
      $num4 = 10;

      Out of interest, look what happens here:

      $num5 = 3;
      $num6 = ++$num5 + $num5 + $num5;  // 12
      // or
      $num7 = 3;
      $num8 = $num7 + ++$num7 + $num7;  // 12

      As for javascript, I guess the values of the variable are captured for the statement before the ++ operator is evaluated… Not what I expected. Actually, the more I think about it, the more it seems like a bug.

        javascript works exactly as I would expected both logically, and given the docs:

        This operator increments (adds one to) its operand and returns a value. If used postfix, with operator after operand (for example, x++), then it returns the value before incrementing. If used prefix with operator before operand (for example, ++x), then it returns the value after incrementing.

        It increments and returns the incremented value.

        but given the php manual is almost identical, I'm surprised it also doesn't work the way I'd expect:

        ++$a Pre-increment Increments $a by one, then returns $a.
        $a++ Post-increment Returns $a, then increments $a by one.

        Note: It doesn't say increment BEFORE the entire statement, but rather increment and return the new value. To me this means the first instance of the variable is still 3, while the second is 4.

          ++ has higher operator precedence than +, so when you have this:

          $num2 = $num1 + ++$num1;

          The steps I would expect the parser to take are the following:

          1. Increment $num1. Since you're doing a pre-increment, it'll replace ++$num1 with this new value.

          2. Evaluate $num1 (which is now four since the increment took place due to higher operator precedence) since it's on the left-hand side of the +.

          3. Evaluates 4 (since it has already replaced ++$num1 with 4) since it's on the right-hand side of the +.

          4. Perform the addition of 4 and 4. Right-hand side of the = is now 8.

          5. Evaluates the assignment operator (i.e. assign 8 to $num2).

          The same process happens with a post-increment, except it evaluates $num1++ as 3 (the un-incremented value) rather than 4 in step #1, giving you $num2 = 4 + 3.

          If the above expression didn't yield 8, then yeah, I'd say there's a bug that is causing operator precedence to be ignored.

          EDIT:

          Derokorian;11036385 wrote:

          Note: It doesn't say increment BEFORE the entire statement

          Sure it does - it's called operator precedence. 🙂

            @ — if it were simply a matter of operator precedence, and ++ had a higher precedence, then wouldn't all of these (following) statements evaluate to 12? Wouldn't this indicate some sort of overlap between the order of operations and the order the variables themselves are evaluated in?

            <?php
            
            $n1 = 3;
            
              $n1 +   $n1 + ++$n1; // 10
              $n1 + ++$n1 +   $n1; // 12
            ++$n1 +   $n1 +   $n1; // 12

            To explain, it seems like the order or operations for addition is being determined first, and then ++ takes precedence…? i.e.,

            ( (    $n1  +    $n1  ) + (++$n1) );  // 10
            ( (    $n1  + (++$n1) ) +    $n1  );  // 12
            ( ( (++$n1) +    $n1  ) +    $n1  );  // 12

            edit:
            where I would expect it would be more like:

            (    $n1  +    $n1  + (++$n1) );  // _then_ ltr; 12
            (    $n1  + (++$n1) +    $n1  );  // ...         12
            ( (++$n1) +    $n1  +    $n1  );  // ...         12
              traq;11036395 wrote:

              $n1 + $n1 + ++$n1; // 10

              Hmm... that's not what I would have expected. Apparently the matter of operator precedence isn't as straightforward as I thought it was. :queasy:

                Oh, it still works. Remember that + is left-associative.

                $n1 + $n1 + ++$n1
                

                When the parser has read [font=monospace]$n1 + $n1[/font] and sees that the next token is [font=monospace]+[/font], the addition operator's associativity comes into play and the expression is equivalent to

                ($n1 + $n1) + ++$n1
                

                And parentheses trump precedence.

                  @, @, @ & @, Thank you very much for this enlightening discussion and clarifications. My special thanks to traq for bringing in two more examples/codes which has finally been clarified by @. Thanks a lot, Dear Weedpacket. Now it seems JavaScript has a problem regarding the matter. Though the logic behind both the languages are same here, as clearly explained by Derokorian, they are displaying different results. Can anyone kindly explain?

                     var num4=num3 + ++num3;
                    

                    JavaScript is evaluating the first "num3" to get its value '3' before it gets far enough to evaluate the preincrement.

                    PHP, on the other hand, doesn't look up the value of (the first) $num3 until it's doing the addition - by which time the increment has already taken place.

                    All of which is a good reason not to write stuff like "$num3 + ++$num3" in the first place. (Douglas Crockford saith to not use "++" or "--" at all.)

                      The JS case is fairly simple; don't do it that way. See 50:43 here:

                      http://www.youtube.com/watch?v=taaEzHI9xyY

                      Key language is "subtle off-by-one errors". You probably found it.

                      It seems to me that saying "$num2=$num1 + ++$num1;" in any language is somewhat akin to a 4-year old playing with matches.

                        The difference is in the associativity for JS and PHP. In PHP the ++/-- operator have right associativity while in js they have none. I bet this is the cause of the difference?
                        JS Precedence
                        PHP Precedence

                          Probably so, although I've seen sources that also say the JS associativity for "++" is also right (Mozilla should know, though, shouldn't they?).

                          Crockford apparently thinks it's just plain buggy (and he has internals knowledge, too). Considering that "no associativity" === "undefined", I would tend to agree; we can't predict what will happen with ++ in JS without explicit associativity.

                          I would agree with Crockford here that a statement without explicit associative properties is a bug waiting for discovery. If we humans can't read it without some difficulty, why would we think the parser (a weekend hack by Eich (or Lerdorf)) is going to do much better?

                            FWIW, I have never even tried to use a variable twice in a statement where one time its getting incremented. I guess because I was never sure how it would work, or if it would work as expected.

                              I think it's less of an associativity issue than what order the vars are evaluated in. PHP obviously looks at both sides of the operator and chooses to evaluate the ++ before "unboxing" variables on either side. Perhaps JS unboxes each var independently, and/or LTR, or something.

                              dalecosp;11036449 wrote:

                              Crockford apparently thinks it's just plain buggy (and he has internals knowledge, too). Considering that "no associativity" === "undefined", I would tend to agree; we can't predict what will happen with ++ in JS without explicit associativity.

                              I would agree with Crockford here that a statement without explicit associative properties is a bug waiting for discovery. If we humans can't read it without some difficulty, why would we think the parser (a weekend hack by Eich (or Lerdorf)) is going to do much better?

                              I'd suggest it's not a bug in the language, rather a huge opportunity for programmers to create their own bugs. The parser seems to know how it works (as we've seen, you can create reliable examples, even if the manual can't quite explain them clearly), but coders generally assume one thing or the other without having a full understanding. Crockford also (for example) advocates against switch statements because of the fall-through risk: clearly not a bug (in fact, an intentional "feature"), but easy for coders to screw up.

                              I completely agree with @, however: I rarely use ++, and when I do, it's in its own statement (e.g., "[font=monospace]$x++;[/font]", not part of an expression, or even a larger statement).

                                traq;11036461 wrote:

                                I'd suggest it's not a bug in the language, rather a huge opportunity for programmers to create their own bugs.

                                That what I tried to say with "a statement without explicit associative properties is a bug waiting for discovery". I (as a programmer) would create a bug, or at least a potential one, if I wrote something like "var2 = var3 + ++var3" ...

                                  sorry; misread that. Yes, I totally agree. : )

                                    @, Thank you very much for being so precise and to the point, once again. @, I have just watched the whole video clip of Crockford for which you provided the links. Its amazing and full of important practical advices. Thank you very much. The original problem I posted here was more a puzzle than a practical one. But you see, through you, Weedpacket, traq and others I have learned a lot, and that is the point. Thank you all for your participation and clarifications. 🙂

                                      The bug is in php which doesn't respect left associativity for addition in all cases.

                                      Derokorian;11036443 wrote:

                                      The difference is in the associativity for JS and PHP. In PHP the ++/-- operator have right associativity while in js they have none. I bet this is the cause of the difference?

                                      Precedence determines in which order operators are handled. Associativity determines in which order operands are evaluated. Operands can be atomic values, variables or expressions. But whatever an operand is does not (should not) affect associativity. It is still an operand.

                                      a = 1;
                                      b = 2;
                                      
                                      a = b = 0;
                                      // this will not evaluate as (a=b), then (b=0)
                                      // but rather as (b=0), then (a=b)
                                      

                                      Unary operators only have one operand, so talking about associativity is pointless:
                                      - In which order is the operand of a unary operator evaluated?
                                      - In the order it is.

                                      Ambiguity can never arise since a unary operator will have an operand (its operand) on one side, while the other side is either empty or contains an operator rather than an operand.

                                      # you will never have
                                      a ! b
                                      x++ y
                                      
                                      # you may have
                                      !b
                                      ++x
                                      
                                      # you may have
                                      a && !b
                                      x++ + y
                                      

                                      On the other hand, it's not really wrong to say that a unary operator which has its operand on the right side is right associative and a unary operator which has its operand on the left side is left associative. I'd still advice against doing so. Because while it isn't wrong, it's still confusing as hell. When you point at something which can only be in one single way and say "Behold, this is this way it is", you will always give people the impression that it could be some other way. Why else would the fact need to be stated? As far as unary operators go, you could of course decide that they should be on the opposite side instead, but its associativity would still be self evident. For example, consider a language which takes explicit type casting operators on the right hand side

                                      i = j (int);
                                      i = j (int) * 6.3;
                                      

                                      And even if you'd allow the operand on both sides of the unary operator, its associativity will still be determined by what side its operand is on in any given case. The other side will still always be empty or contain an operator.

                                      In the php docs for operator precedence and associativity, ++ and -- are listed together with other unary operators that all are written to the left of their operand (int), (float), @ etc. Thus, if you wish to talk about associativity for this group of operators, it will have to be right, but that also means that you are explicitly NOT talking about post-increment and post-decrement operators. They are in fact not listed in that table.

                                      Precedence lets you know in which order to deal with operators

                                      y + ++x
                                      // Increment has higher precedence than addition, so the expression is evaluated as
                                      y + (++x)
                                      
                                      $i = (int) 2.3 + 3.5;
                                      # (int) has higher precedence addition, 
                                      $i = ((int) 2.3) + 3.5
                                      

                                      Back to a + b + c. It has left assoc, which means evaluating the leftmost operand, a, first. Looking at the second addition operator, its left operand is an expression consisting of a + b, which is why a + b is evaluated before c. Once again, compare this to how right associativity works when it comes to a = b = c, where c is evaluated before b = c is evaluated before a = b (where b now has the same value as c) is evaluated.

                                      A quick detour to


                                      In the case of

                                      $x = 5;
                                      $y = $x++ + $x
                                      # $y is 11
                                      

                                      They have it correct. (x++) is evaluated first, and it is the value of x (5). Then x is incremented. Next up the right hand side is evaluated which is 6 since x has now been incremented.

                                      However, in the other case they really do get it wrong

                                      $x = 5;
                                      $y = $x + ++$x
                                      # $y should be 11, but it is 12 in php
                                      

                                      Due to the left associativity of addition, x should still be evaluated first, and it is x (5). Then (++x) should be evaluated and it should increment x before returning 6. Then addition should be performed for 5 and 6. It is, or should be, impossible for any changes to effect evaluation which (should) already have happened.
                                      There are two cases that can be correct, depending on wether you define addition to be left or right associative. Either (if dealing with right-associative addition) the first case should be 10 and the second case should be 12, or (left-associative addition) both cases should be 11.

                                      Back to javascript - which actually gets it right

                                      x = 5;
                                      y = x++ + x;
                                      // y is 11
                                      
                                      x = 5;
                                      y = x + ++x;
                                      // y is still 11 - as expected