KeyExistsQ[] but for functions?

Is there a good way to check if, say, f[5] has been defined if f is a function, similar to KeyExistsQ[f,5] for associations? I want it to return false if f[x_] has a delayed assignment but f[5] in particular has not been assigned a value.

f[x_] := f[x] = x^2
KeyExistsForFunctionsQ[f,5]
f[5];
KeyExistsForFunctionsQ[f,5]
(*False, True*)

• Have a look at DownValues[f] and assoc = Association[Extract[#, {1, 1}, Hold] -> Extract[#, 2, Hold] & /@ DownValues[f]] . It's then possible to check KeyExistsQ[assoc, Hold[f[5]]] – flinty Aug 21 '20 at 13:55

Here's a simple method for checking if any of the down values of a function matches f[5] literally. It's a good use case for Verbatim:

KeyExistsForFunctionsQ[fun_, arg_] := AnyTrue[
Keys[DownValues[fun]],
MatchQ[#, Verbatim[HoldPattern[fun[arg]]]] &
]


This method can be extended to checking other types of down values of functions as well. For example:

ValueQWithoutEval[fun_, arg_] := AnyTrue[
Keys[DownValues[fun]],
MatchQ[Hold[fun[arg]], Hold[#]] &
]


This will check if any of the down values of a function will match fun[arg] without actually trying to evaluate it (because it might be expensive, for example). Note that this will not work for assignments that use Condition in the r.h.s. of := like

f[x_] := With[{y = 2 x + 1}, y /; PrimeQ[y]]


For functions like that, you can't avoid evaluating the function at least partially to find out if the argument matches.

DownValues aren't the only method for caching previously computed results. For instance you can use an association,

ClearAll[fdata, f]
fdata = <||>;
f[x_] := Lookup[fdata, x, fdata[x] = x^2]


Now when you compute a value it is stored in fdata,

In[21]:= f /@ Range[3]

Out[21]= {1, 4, 9}

In[22]:= KeyExistsQ[fdata, #] & /@ Range[4]

Out[22]= {True, True, True, False}

ClearAll[keyExistsQ]
keyExistsQ = Function[{func, arg},
KeyExistsQ[DownValues[func], HoldPattern[func[arg]]], HoldAll];


Example:

ClearAll[f]
f[x_] := f[x] = x^2

{keyExistsQ[f, 5], f[5], keyExistsQ[f, 5]}

{False, 25, True}

• As noted by Sjoerd in his answer this will not work for assignments that use Condition in the r.h.s. – kglr Sep 28 '20 at 22:59