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