KeyExistsQ []ですが、関数用ですか?

Aug 21 2020

たとえば、関連付けのf[5]場合fと同様に、が関数であるかどうかが定義されているかどうかを確認する良い方法はありKeyExistsQ[f,5]ますか?f[x_]割り当てが遅れているがf[5]、特に値が割り当てられていない場合は、falseを返したいです。

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

回答

9 SjoerdSmit Aug 21 2020 at 22:41

関数のダウン値のいずれかがf[5]文字通り一致するかどうかを確認する簡単な方法を次に示します。これは次の良いユースケースですVerbatim

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

このメソッドは、関数の他のタイプのダウン値をチェックするように拡張することもできます。例えば:

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

これにより、関数のダウン値のいずれかがfun[arg]実際に評価を試みることなく一致するかどうかがチェックされます(たとえば、コストがかかる可能性があるため)。これはCondition:=likeのrhsで使用される割り当てでは機能しないことに注意してください

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

そのような関数の場合、引数が一致するかどうかを確認するために、少なくとも部分的に関数を評価することを避けることはできません。

9 JasonB. Aug 21 2020 at 21:49

DownValues以前に計算された結果をキャッシュする方法はこれだけではありません。たとえば、関連付けを使用できます。

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

これで、値を計算すると、に格納されます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];

例:

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

{keyExistsQ[f, 5], f[5], keyExistsQ[f, 5]}
{False, 25, True}