Can anyone provide insight on what's going on here?
First I define a new Set behavior for a symbol:
mySym /: Set[mySym[f_], v_] := v
mySym[1] = 2
(* Out *) 2
mySym[1]
(* Out *) mySym[1]
Works great
But if we provide an alias for this symbol the UpValues never get called:
ms = mySym;
ms[1] = 2
(* Out *) 2
mySym[1]
(* Out *) 2
Even more, if we pre-Evaluate that ms we still have an issue:
Evaluate[ms][1] = 3
(* Out *) 3
mySym[1]
(* Out *) 3
Although With does the appropriate thing:
With[{m = ms},
m[1] = 4
]
(* Out *) 4
mySym[1]
(* Out *) 3
What's the cause of that? It's single-handedly nixed an OO implementation I was working on.
Answer
But if we provide an alias for this symbol the UpValues never get called:
Set is HoldFirst. That means that its first argument does not get evaluated before it is passed to Set. ms[1] = 2 never gets transformed to mySym[1] = 2.
It is true that internally Set will examine its first argument and will evaluate it sometimes. That is why in this case the definition mySym[1] = 2 gets created. But that happens internally within Set. The expression mySym[1] = 2, which could trigger the UpValues rule, never materializes.
Even more, if we pre-Evaluate that ms we still have an issue:
Evaluate works only at level 1 within a held expression.
Hold[Evaluate[1 + 1]]
(* Hold[2] *)
Hold[{Evaluate[1 + 1]}]
(* Hold[{Evaluate[1 + 1]}] *)
Whenever the evaluator encounters a symbol with a Hold* attribute, it will check for any Evaluate within the first level only, and act accordingly.
Comments
Post a Comment