# Is it possible to change the order that symbol definitions are checked? (DownValues vs UpValues)

Suppose I have the function f with the following definition assigned to it:

f // ClearAll;
f // Attributes = { HoldAll };
f /: HoldPattern[ f[x_] + f[y_] ] := upvalue;


If I evaluate f[x] + f[y], I get upvalue as expected. Now if I instead use the definitions:

f // ClearAll;
f // Attributes = { HoldAll };
f /: HoldPattern[ f[x_] + f[y_] ] := upvalue;
f[x_] := downvalue;


the last one will take precedence, so f[x] + f[y] gives 2 downvalue. From a trace, it's pretty easy to see why this happens, since the second argument isn't seen until after the first has been evaluated:

(* In *)
Column[ Trace[ f[x] + f[y], TraceOriginal -> True ] ]

(* Out *)
f[x] + f[y]
{Plus}
{f[x], {f}, f[x], downvalue}
{f[y], {f}, f[y], downvalue}
downvalue + downvalue
2 downvalue
{Times}
{2}
{downvalue}
2 downvalue


However, I'd like to know if there's good way to prioritize the first definition so I get upvalue instead? A possible workaround would be to do something like this:

(* In *)
Hold[ f[x] + f[y] ] /. UpValues[f] /. DownValues[f] // ReleaseHold

(* Out *)
upvalue


but that's a pretty ugly solution. Anyone have any better ideas?

Without thinking about any consequences, one idea popped into my mind. First, your definitions for f with the DownValues. I made it a bit more interesting:

ClearAll[f];
f // Attributes = {HoldAll};
f /: HoldPattern[f[x_] + f[y_]] := upvaluesSeen[f[x], f[y]];
f[x_] := downvalue[x]


How about a small wrapper function that temporarily deletes all DownValues of f. With this, the UpValues can act and as soon as we leave the wrapper, we go back to normal. At this point, you should instantly think of InternalInheritedBlock.

SetAttributes[prioritizeUpvalues, {HoldAll}];
prioritizeUpvalues[expr_, f_Symbol] := InternalInheritedBlock[{f},
DownValues[f] =.;
expr
]


Now, here we go

prioritizeUpvalues[f[x] + f[y], f]
(* upvaluesSeen[downvalue[x], downvalue[y]] *)


or

prioritizeUpvalues[f[x]*f[y], f]
(* downvalue[x] downvalue[y] *)


or

f
(* downvalue *)


Adapting Leonid's method for How do you set attributes on SubValues?

ClearAll[f, g];
SetAttributes[{f, g}, HoldAll];
g /: g[x_] + g[y_] := upvalue;
f[x_] := downvalue

f :=
With[{stack = Stack[_] /. HoldPattern[f] :> g},
With[{foo = Cases[stack, Alternatives @@ _ /@ First /@ UpValues @ g]},
g /; foo =!= {}
] /; stack =!= {}
]


Now:

f
f
f + f

downvalue

downvalue

upvalue


You can hide your workaround in $Pre: SetAttributes[specialEvaluate, HoldAll] specialEvaluate[expr_] := ReleaseHold[ Hold[expr] /. UpValues[f] ]$Pre = specialEvaluate;


And now:

f + f
(* Out: upvalue *)

• A caveat: this only works on user input rather than expressions generated internally. – Mr.Wizard Sep 21 '15 at 0:48