KeyExistsQ[] pero para funciones?

Aug 21 2020

¿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

9 SjoerdSmit Aug 21 2020 at 22:41

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.

9 JasonB. Aug 21 2020 at 21:49

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}
kglr Sep 29 2020 at 05:57
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}