# Extract DownValues used in function evaluation

Is there a convenient way to find out which DownValues is used when calling a function? As an example, consider the following function:

abs[Complex[0,n_]] := Complex[0,Abs[n]]

abs[n_?NumberQ] := Sign[n] n

abs[n_?NumericQ] /; MemberQ[{-1,0,1}, Sign[n]] := Sign[n] n

abs[x_] /; InternalSyntacticNegativeQ[x] := -x

abs[x_] := x


which is just some random code. Now, I want to know which DownValues fired when I evaluate abs[N@I]? Obviously, this example is simple enough that I can figure out which DownValues would fire by inspection, assuming the DownValues occur in the order listed above. However, suppose there are many more DownValues, or suppose you don't to spend time perusing the DownValues to figure out which one would fire for a particular input. Is there some simple function that will give me which DownValues has fired?

• Somewhat related: (334) Sep 2, 2017 at 11:58

Here is a simple utility function that I use all the time:

SetAttributes[ExtractDownValues, HoldAll]

ExtractDownValues[sym_[args__]] := ExtractDownValues[sym,args]
ExtractDownValues[sym_,args__] := Cases[
DownValues[sym], _[h_, _] /; MatchQ[Unevaluated[sym[args]], h]
]


ExtractDownValues @ abs[N @ I]


{HoldPattern[abs[n_?NumberQ]] :> Sign[n] n, HoldPattern[abs[x_]] :> x}

I keep the full list of matching DownValues because the real matching DownValues can be hard to determine syntactically if any of the DownValues use Condition.

This could be useful.

I attempted to handle Condition; maybe it can be cleaned up some.

SetAttributes[capture, HoldFirst]

capture[expr : h_[___]] :=
Module[{dv, rls, i = 1, cond},
SetAttributes[cond, HoldAll];
cond[a_, b_] := Condition @@ Hold[a, b];
cond[a_] := a;

dv = DownValues[h];
rls = Cases[dv, (L_ :> Verbatim[Condition][R_, C_] | R_) :> cond[L, C] -> i++];
AppendTo[rls, _ -> {}];

dv[[ Replace[Unevaluated[expr], rls] ]]
]


Test:

abs[N@I] // capture

HoldPattern[abs[n_?NumberQ]] :> Sign[n] n


Right-hand-side condition:

foo[a_] := bar /; a

foo[True]  // capture
foo[False] // capture

HoldPattern[foo[a_]] :> bar /; a

{}
`