# Correct way to see domain of function using DownValues?

Here's a simple function g defined for the natural numbers 1 through 10:

Table[g[i] = i^2, {i, 1, 10}]

I now want to find the domain of g, namely the natural numbers 1 through 10. However:


In[228]:= dv = DownValues[g]

Out[228]=
{HoldPattern[g[1]] :> 1, HoldPattern[g[2]] :> 4,
HoldPattern[g[3]] :> 9, HoldPattern[g[4]] :> 16, HoldPattern[g[5]] :> 25,
HoldPattern[g[6]] :> 36, HoldPattern[g[7]] :> 49, HoldPattern[g[8]] :> 64,
HoldPattern[g[9]] :> 81, HoldPattern[g[10]] :> 100}

In[231]:= dv[[4]]

Out[231]= HoldPattern[g[4]] :> 16

In[232]:= dv[[4,1]]

Out[232]= HoldPattern[g[4]]



The problem: nothing I do to dv[[4,1]] will give me back 4. ReleaseHold releases the hold and gives me 16 as expected. I found a workaround:


In[244]:= (dv[[4,1]] /. g -> Null)[[1,1]]

Out[244]= 4


but this seems bad (even if I replace Null w/ a temporary variable or whatever).

dom = Cases[DownValues[g], g[x_] :> x, Infinity]
(* {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} *)


If you have definitions with multiple arguments, e.g. g[-1, -2] = Pi, you can do

dom = Cases[DownValues[g], g[x__] :> {x}, Infinity]
(* {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {-1, -2}} *)


The range is then very simply

ran = g @@@ dom
(* {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, π} *)

#[[1, 1, 1]] & /@ DownValues[g]
(* {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} *)

• alternative: ReleaseHold[First /@ DownValues[g] /. g -> Identity]. Aug 12, 2018 at 19:12
• Thanks, this works! I always thought dv[[4,1,1,1]] was the same thing as dv[[4,1,1]][[1]] but apparently not, since dv[[4,1,1]] is just the numeric value 16. Does this magic work only because of the Hold value? I'm guessing when I type dv[[4,1,1]] it gets evaluated to 16, but it's "raw form" is somehow different. Ah, got it dv // FullForm shows what this really is.
– user1722
Aug 12, 2018 at 19:12