Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

This line returns 3:

x = 1; ++++x

enter image description here

However, the value of x after the increment is only 2. Similarly, this line returns 5, while the value of x is again only 2.

x = 1; ++++++++x

enter image description here

Why does it return 3 and 5 respectively in the above examples?


(This question is intended as a puzzle, and to encourage people to think through an opaque evaluation chain.)

share|improve this question
    
I'm too sleepy to write an answer but the explanation is clear if you TracePrint, and consider the HoldAll causes evaluating to from outside to inside as we disussed in chat the other day –  Szabolcs Feb 25 '12 at 0:03
    
@Szabolcs this might be more involved than you think, but of course I don't know what you think. I added an example you should also consider. –  Mr.Wizard Feb 25 '12 at 0:09
    
That's all consistent with my understanding. I wrote a short answer. –  Szabolcs Feb 25 '12 at 0:22
2  
Doesn't it happen on all releases of 8? I get exactly the same what you get in 7. Is it possible that those who got a different result simply forgot to set a value to x? –  Szabolcs Feb 25 '12 at 10:02

3 Answers 3

up vote 13 down vote accepted

TracePrint will show you what happens:

PreIncrement takes it's argument x, evaluates it (let's call the result result), then evaluates x = result+1. Note that PreIncrement has HoldFirst.

Now ++(++x) evaluates ++x first yielding 2, then evaluates (++x) = 2+1 resulting in an error (trying to assign to PreIncrement) and returning 3.

This also explains why adding yet another layer of PreIncrement will increment the result again.


Mathematica graphics


Here's a self-implemented ++ to make the above more clear. The behaviour is exactly the same:

Mathematica graphics

share|improve this answer
    
Alright, I yield. –  Mr.Wizard Feb 25 '12 at 0:28

A quick test shows that assignment returns the right hand side even if the left hand side is protected:

Protect[a]; a=b
(*
==> b
*)

Now ++x (i.e. Preincrement[x]) is equivalent to x=x+1. Indeed, this is true even for the argument evaluation:

++foo[Print["x"]];

outputs "x" twice (and gives a "recursion limit exceeded"), just like

foo[Print["x"]]=foo[Print["x"]]+1;

Therefore

++++x

is equivalent to

++x = ++x +1

where the left side is unevaluated (due to HoldFirst) but cannot be set (due to Protected), but the expression nevertheless evaluates and returns the result of ++x + 1, which of course increments x once, but gives 2 more than the old value of x.

share|improve this answer

Using FullForm on the expression yields

++++x // FullForm
PreIncrement[PreIncrement[x]]

PreIncrement increments the value of its argument by one, and returns the new value; notice that it has the attribute HoldFirst. Mathematica 8 issues a warning here that PreIncrement is protected and cannot be incremented, while strangely enough printing 3 nevertheless. In any case, x is incremented only once (by the inner PreIncrement), giving it a value of 2.

share|improve this answer
    
"while curiously enough printing 3 nevertheless" -- that's rather the point of the question, isn't it? –  Mr.Wizard Feb 25 '12 at 0:01
    
I'm running 8.0.4 and I get ++++x returned unevaluated, alongside with the messages, of course. –  rcollyer Feb 25 '12 at 0:04
    
@rcollyer oh nuts, they fixed it. –  Mr.Wizard Feb 25 '12 at 0:05
    
@rcollyer I'm running 8.0.4 and it evaluates (plus the mentioned warning). Odd –  David Feb 25 '12 at 0:08
    
I get PreIncrement[PreIncrement[x]] when using FullForm, but ++++x when not. –  rcollyer Feb 25 '12 at 1:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.