KeyExistsQ[] ma per le funzioni?

Aug 21 2020

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

9 SjoerdSmit Aug 21 2020 at 22:41

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 Conditionnella 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.

9 JasonB. Aug 21 2020 at 21:49

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