# Another difference between Set and Setdelayed. Evaluation shortcut?

A little while ago I wondered why

f[x_] = f[x]


gives an infinite iteration. I ended up discovering the following difference in evaluation between Set and SetDelayed with Evaluate.

count = 0;
ClearAll@a
a /; (count++ < 20) = {a}
a // OwnValues
count = 0;
a


Output

{{{{{{{{{{{{{{{{{{{{{a}}}}}}}}}}}}}}}}}}}}}
{HoldPattern[a /; count++ < 20] :> {a}}
{a}


and

count = 0;
ClearAll@b
b /; (count++ < 20) := Evaluate@{b}
b // OwnValues
count = 0;
b


Output

{HoldPattern[b /; count++ < 20] :> {b}}
{{{{{{{{{{{{{{{{{{{{b}}}}}}}}}}}}}}}}}}}}


Can somebody explain the difference? Can we say that there is an evaluation shortcut at work here?

Related

This is a follow up question: Strange results of definitions using OwnValues

Why x = x doesn't cause an infinite loop, but f[x_] := f[x] does?

Does Set vs. SetDelayed have any effect after the definition was done?

-
A nice tool I made says SetDelayed is not called in a usual way in the last example – Jacob Akkerboom Jan 10 '14 at 16:26
Ah, I see now. Thanks @Rojo – Mr.Wizard Jan 10 '14 at 17:13
It's another cache Update[] related mystery – Rojolalalalalalalalalalalalala Jan 10 '14 at 17:17
@Rojo I noticed the same thing myself. – Mr.Wizard Jan 10 '14 at 17:18
As to the second, there are several symbols that have special ways of being set. Perhaps through UpValues (or perhaps you like upcode better :P). Clearly the XValues are some of those. Perhaps, when they overloaded the SetDelayed versions, they forgot to return Null? – Rojolalalalalalalalalalalalala Jan 10 '14 at 17:22

Extended comment. Also: If Rojo wants to post an answer, I can delete this

It seems Rojo was right, guessing that it had to do with Update.

count = 0;
ClearAll@a2
a2 /; (Update[Unevaluated@a2]; count++ < 20) = {a2}
a2 // OwnValues
count = 0;
a2


Output

{{{{{{{{{{{{{{{{{{{{{a2}}}}}}}}}}}}}}}}}}}}}
{HoldPattern[a2 /; (Update[Unevaluated[a2]]; count++ < 20)] :> {a2}}
{{{{{{{{{{{{{{{{{{{{a2}}}}}}}}}}}}}}}}}}}}


Strange that there is a pair of brackets missing though...

-

Also an extended comment; using Update[] makes the first recursion behave as expected:

count = 0;
ClearAll@a
a /; (count++ < 20) = {a};
count = 0;
Update[]
a

{{{{{{{{{{{{{{{{{{{{a}}}}}}}}}}}}}}}}}}}}


Apparently the LHS condition is affected by the use of Set versus SetDelayed. Certainly worth more exploration, but for me that will have to wait.

-
Hm you have the same difference in number of brackets, if you remove the semicolon after a /; (count++ < 20) = {a}. Strange strange – Jacob Akkerboom Jan 10 '14 at 18:04