KeyExistsQ[] pero para funciones?
¿Existe una buena manera de comprobar si, por ejemplo, f[5]se ha definido si fes una función similar a KeyExistsQ[f,5]para asociaciones? Quiero que devuelva falso si f[x_]tiene una asignación retrasada pero f[5]en particular no se le ha asignado un valor.
f[x_] := f[x] = x^2
KeyExistsForFunctionsQ[f,5]
f[5];
KeyExistsForFunctionsQ[f,5]
(*False, True*)
Respuestas
Aquí hay un método simple para verificar si alguno de los valores inferiores de una función coincide f[5]literalmente. Es un buen caso de uso para Verbatim:
KeyExistsForFunctionsQ[fun_, arg_] := AnyTrue[
Keys[DownValues[fun]],
MatchQ[#, Verbatim[HoldPattern[fun[arg]]]] &
]
Este método también se puede extender para verificar otros tipos de valores bajos de funciones. Por ejemplo:
ValueQWithoutEval[fun_, arg_] := AnyTrue[
Keys[DownValues[fun]],
MatchQ[Hold[fun[arg]], Hold[#]] &
]
Esto verificará si alguno de los valores bajos de una función coincidirá fun[arg]sin intentar evaluarlo (porque podría ser costoso, por ejemplo). Tenga en cuenta que esto no funcionará para las asignaciones que se usan Conditionen el rhs de :=like
f[x_] := With[{y = 2 x + 1}, y /; PrimeQ[y]]
Para funciones como esa, no puede evitar evaluar la función al menos parcialmente para averiguar si el argumento coincide.
DownValuesno son el único método para almacenar en caché los resultados calculados previamente. Por ejemplo, puede utilizar una asociación,
ClearAll[fdata, f]
fdata = <||>;
f[x_] := Lookup[fdata, x, fdata[x] = x^2]
Ahora, cuando calcula un valor, se almacena en 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];
Ejemplo:
ClearAll[f]
f[x_] := f[x] = x^2
{keyExistsQ[f, 5], f[5], keyExistsQ[f, 5]}
{False, 25, True}