I am asking this question simultatenously with this one, which is strongly related.
I was trying to see if I could create the behaviour as in that question without using Condition
by setting OwnValues
. I ran into the following strange behaviour.
The following gives an infinite recursion
Clear[c]
OwnValues[c] = {HoldPattern[c] -> {c}}
So does this
Clear[d]
OwnValues[d] := {HoldPattern[d] -> {d}}
But this does not
Clear[e]
OwnValues[e] := {HoldPattern[e] -> Unevaluated@{e}}
Actually this last piece evaluates to something other than Null
, which is not what we expect from SetDelayed
. Simpler expressions of similar form will also return something. This is what the aside here is about.
Question: Can somebody explain what is going on here? Why do these definitions cause infinite recursions?
Aside
Maybe I will write a separate question about this ;)
Tool
I have made the following tool that can show us when a particular function is being called, and with what arguments. It uses Print
to display this information. Note that it is quite buggy. For now let's only use it on SetDelayed
. Making both SetDelayed
and Set
print this way crashes the kernel I think. This is the tool.
SetAttributes[letPrint, HoldAll];
letPrint[symb_] :=
(
ClearAttributes[symb, Protected];
DownValues[symb] = {};
With[
{uq = Unique[]},
uq = False;
expr : symb[___] /; (uq = ! uq) := (Print[
Column[{uq, ToString[Unevaluated[symb]],
HoldForm@InputForm[expr]}]]; expr)
]
)
Now we can do
(*warning, overloads and Unprotects SetDelayed*)
letPrint@SetDelayed
We then have that
Clear[aaa, bbb]
aaa := bbb
Prints
True (*not really meaningful*)
SetDelayed
aaa:=bbb
but
Clear[a]
OwnValues[a] = {HoldPattern[a] :> 1};
does not print anything. My suspicion is that there is some internal code associated with OwnValues
that prevents the expression with head SetDelayed
from being evaluated like normal.
To restore SetDelayed
, I think you can do
Clear@SetDelayed; Protect@SetDelayed