KeyExistsQ[] ma per le funzioni?
C'è un buon modo per verificare se, diciamo, f[5]
è stato definito se f
è una funzione, simile a KeyExistsQ[f,5]
per le associazioni? Voglio che restituisca false se f[x_]
ha un'assegnazione ritardata ma f[5]
in particolare non è stato assegnato un valore.
f[x_] := f[x] = x^2
KeyExistsForFunctionsQ[f,5]
f[5];
KeyExistsForFunctionsQ[f,5]
(*False, True*)
Risposte
Ecco un metodo semplice per verificare se uno qualsiasi dei valori inferiori di una funzione corrisponde f[5]
letteralmente. È un buon caso d'uso per Verbatim
:
KeyExistsForFunctionsQ[fun_, arg_] := AnyTrue[
Keys[DownValues[fun]],
MatchQ[#, Verbatim[HoldPattern[fun[arg]]]] &
]
Questo metodo può essere esteso anche al controllo di altri tipi di valori inferiori delle funzioni. Per esempio:
ValueQWithoutEval[fun_, arg_] := AnyTrue[
Keys[DownValues[fun]],
MatchQ[Hold[fun[arg]], Hold[#]] &
]
Questo verificherà se uno qualsiasi dei valori inferiori di una funzione corrisponderà fun[arg]
senza effettivamente tentare di valutarlo (perché potrebbe essere costoso, ad esempio). Si noti che questo non funzionerà per gli incarichi che usano Condition
nella parte destra di :=
like
f[x_] := With[{y = 2 x + 1}, y /; PrimeQ[y]]
Per funzioni del genere, non puoi evitare di valutare la funzione almeno in parte per scoprire se l'argomento corrisponde.
DownValues
non sono l'unico metodo per memorizzare nella cache i risultati calcolati in precedenza. Ad esempio puoi usare un'associazione,
ClearAll[fdata, f]
fdata = <||>;
f[x_] := Lookup[fdata, x, fdata[x] = x^2]
Ora, quando calcoli un valore, viene memorizzato 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];
Esempio:
ClearAll[f]
f[x_] := f[x] = x^2
{keyExistsQ[f, 5], f[5], keyExistsQ[f, 5]}
{False, 25, True}