0

Let's evaluate this code for swapping two variables :

var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );

I was expecting that new value of a should be 3 and value of b should be 5. But I got values as a = 0 and b = 5;

I went and read the EcmaScript Arithmetic expression and found that this will be evaluated from left-to-right. ( but not completely clear ).

So I tried this one

var a = 5, b = 3; 
a = ( ( b = ( a = a+b ) - b ) - a );

Now I got a = -3 and b = 5. Can somebody explain me why this is happening like this ?

Shidhin Cr
  • 868
  • 8
  • 19

5 Answers5

2

Here is the explanation, I hope it is clear because it is not so obvious. JS and all other languages create a tree to evaluate expressions. The tree assigns a weight to each operator depending on their position and on the braces.

First, here is the steps JS would process the expression:

Step 0. a = ( a - ( b = ( a = a+b ) - b ) );   a=5, b=3
Step 1.                   a = a+b              a=8, b=3
Step 2.             b = a - b                  a=8, b=5 
Step 3. a = a - b                              a=0, b=5

At each step it processes one operator.

And this is the tree it creates from you expression:

    =
  /   \
 a     - 
     /    \
   a       =
          /  \   
         b    -            
             / \
            =   b
           /  \
          a    +
              / \
             a   b

The tree is then processed from bottom to top.

KLiFF
  • 382
  • 2
  • 18
  • But , in the third step `a = a-b` should give me result as `a=3 and b=5`. isn't it ? Because step2 changed the value of `a and b` as `a = 8 and b =3`. I'm bit confused – Shidhin Cr Sep 27 '13 at 09:45
  • Look at my answer: http://stackoverflow.com/a/19045816/1324929. What @KLiFF fails to mention is that with assignment, the first step is expression evaluation on the right side. Thus, a = ( a -( b = ( a = a+b ) - b ) ) becomes a = ( 5 -( b = ( a = 5+3 ) - 3 ) ). After that, the right side, from inner parens to outer parens, a = 5+3, a becomes 8, b = 8-3, b becomes 5 and finally a = 5-5, a becomes 0, b remains 5. – itmitica Sep 27 '13 at 10:04
  • not exactly. The tree is processed from left to right, otherwise a = 8 in your first left node. – njzk2 Sep 27 '13 at 10:07
  • It is indeed very confusing, but here is the explanation: The a from the left was already evaluated and has a value of 5, the a from the right is is the result of the calculations from the right branch of the tree and has a value of 8. So there is in fact an a and an a'. – KLiFF Sep 27 '13 at 10:19
  • How the tree is processed exactly ? Is it from bottom to top OR left to right ? I read that arithmetic expressions are evaluated from left to right. If I apply the same logic here, then it makes sense .. It produces the correct ouput .. Only one more clarification I need is when processing the left node, it should be processing all of it's child nodes before moving to the right node .. isn't it ? – Shidhin Cr Sep 27 '13 at 13:19
  • That's correct, in this example the 'b' at the right of `( a = a+b ) - b` is evaluated after the 'b' at the left side. here is a code you can use to see what branch is evaluated in what order using firebug: `var a = 5, b = 3; var say = function(t, v) { console.log(t + "." + v); return v;} a = say("left", a) -( b = ( a = a + say("left-b", b) ) - say("right-b", b))` – KLiFF Sep 27 '13 at 13:46
1
var a = 5, b = 3;
a = ( ( b = ( a = a+b ) - b ) - a );

It will operate in this way.

a = a + b //8
b = a - b //8-3=5
a = b - a //5-8=-3
Cameron
  • 36
  • 3
1

As you said, the expression is evaluated from left to right, meaning the first time a is encountered, its value is still 5. This comes down to:

var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );
a = 5 - (b = (a=(5+3)) - b);
a = 5 - (b = 8 - b);
a = 5 - 5; AND b = 5

In the second one, the a value is evaluated after the assignment because it is on the right

var a = 5, b = 3;
a = ( ( b = ( a = a+b ) - b ) - a );
a = ( ( b = 8 - b ) - a ); AND a = 8
a = ( 5 - 8 ); AND a = 8; AND b = 5;
a = - 3;

It all comes down to the order of the evaluation of the operands.

Typically in the first case, a is evaluated to 5, then b = ( a = a+b ) - b is evaluated, and only during this evaluation the value of a changes, but is not backported.

In the second example, ( b = ( a = a+b ) - b ) is evaluated first, changing the a value to 8, then a is evaluated, and is found to be 8

A more trivial example is :

var a = 5
a = a + (a = 2)
// a = 7

a is evaluated to 5, then (a = 2) is evaluated to 2 and a is set to 2, then 5+2 is evaluated and a is set to 7.

On the other hand :

var a = 5
a = (a = 2) + a
// a = 4

(a = 2) is evaluated to 2 and a is set to 2, then a is evaluated to 2, then 2+2 is evaluated and a is set to 4

njzk2
  • 38,969
  • 7
  • 69
  • 107
0
a = ( a -( b = ( a = a+b ) - b ) ) 

is similar to this

a = ( 5 -( b = ( a = 5+3 ) - 3 ) ) // a = 8
// a = ( 5 - ( b = 8 - 3 ) ) // b = 5
// a = ( 5 - 5 ) // a = 0

meaning it will replace a and b on the left side of = in one go with the same initial values, it's not similar to this sequence

a = a+b; // a = 8
b = a-b; // b = 5
a = a-b; // a = 3

as you expect.

itmitica
  • 501
  • 3
  • 10
0
var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );

1) a = a(5) - (rest of expression, where 2 parts will be calculated soon)

2) b = (a = a+b // and it's still not calculated) - b (which is 3, because new b is not changed yet)

3) a = 5(a) + 3(b) = 8

4) b(we are back to point 2) = 8(new a) - 3(old b) = 5

5) a(point 1) = 5(old a) - 5(new b) = 0

New a = 0, new b = 5

var a = 5, b = 3; 
a = ( ( b = ( a = a+b ) - b ) - a );

1) b = ( a = a+b ) - 3(b)

2) a = 5(a) + 3(b) = 8

3) b = 8(new a) - 3(old b) = 5

4) a(final) = 5(new b) - 8(new a) = -3

New a = -3, new b = 5

I hope it's readable :D

Nikolay Talanov
  • 706
  • 4
  • 15