2
$\begingroup$

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
$\endgroup$
0

1 Answer 1

7
$\begingroup$

I don't think it is related to your other question.

It seems that SetDelayed applied to the XValues functions behaves like Set in the sense that it returns the stuff it has assigned instead of returning Null.

OwnValues[c] = {HoldPattern[c] -> {c}} will give an infinite recursion because it will want to return something that requires the evaluation of c, after it was assigned to {c}.

The second example is the same, due to the above mentioned peculiarity.

OwnValues[e] := {HoldPattern[e] -> Unevaluated@{e}} will not because it returs something that doesn't require the evaluation of e. And even if it did, that last assignment would replace e with Unevaluated@{e} which won't iterate again

$\endgroup$
2
  • $\begingroup$ But why evaluation of OwnValues[e] := {HoldPattern[e] -> Unevaluated@{e}} returns something other than Null? "Usual" delayed definitions do not return anything. $\endgroup$ Jan 11, 2014 at 1:58
  • 2
    $\begingroup$ @AlexeyPopkov. The behaviour of SetX for the XValues is different in more than one way, it is overloaded. For example, it checks that you are assigning valid rules. Perhaps they just forgot to return Null when they overloaded it, or perhaps there's a reason :P. It is clearly inconsistent, but it seems to be that way $\endgroup$
    – Rojo
    Jan 11, 2014 at 3:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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