“ defined”と同等Mathematicaで
-
22-07-2019 - |
質問
シンボルの名前を文字列として受け取り、そのシンボルが既に定義されているかどうかを返す関数が必要です。関数 ValueQ
は近いですが、関数名に対してFalseを返します。また、文字列ではなくシンボルを取ります。
例:
defined["N"] --> True (predefined function N)
defined["x"] --> False
x = 7;
defined["x"] --> True (x is now defined)
defined["7"] --> True (7 is a number)
f[x_] := 2x
defined["f"] --> True (f has DownValues)
g[x_][y_] := x+y
defined["g"] --> True (g has SubValues)
PS:DownValuesとSubValuesの両方をチェックする必要があることを指摘してくれたPillsyに感謝します。
解決 2
これを一緒にまとめてみたが、うまくいくようだ:
defined[s_] := ToExpression["ValueQ[" <> s <> "]"] ||
Head@ToExpression[s] =!= Symbol ||
ToExpression["Attributes[" <> s <> "]"] =!= {} ||
ToExpression["DownValues[" <> s <> "]"] =!= {} ||
ToExpression["SubValues[" <> s <> "]"] =!= {}
うまくいけば、よりきれいなソリューションがあります。
PS:DownValuesとSubValuesの両方をチェックする必要があることを指摘してくれたPillsyに感謝します。
他のヒント
Namesがトリックを行うべきだと思う:
Names [&quot; string&quot;]は、 に一致するシンボルの名前 文字列。
Names [&quot; foo&quot;]が{}を返す場合、fooの定義はありません。そうでない場合は{&quot; foo&quot;}を返します。 したがって、関数「定義」は次のように実行できます。
defined[str_] := Names[str] != {}
少なくとも7はシンボルではないため、これは「7」では機能しないためです。このケースは、たとえばNumberQで個別に処理できます。
また、Symbolを使用して文字列からシンボルを作成し(シンボルの自動生成に有用)、Definitionを使用してシンボルの定義を確認できます。
Symbol [&quot; name&quot;]は、 指定された名前。
Definition [symbol]は、 シンボルの定義。
編集:Namesが返すものを見るよりも、NameQ [&quot; name&quot;]が与えられた名前が存在するかどうかを知らせます。ただし、シンボルに明示的な定義があるかどうかはまだ言及されていません。
DownValues
を使用して、「関数」があるかどうかを確認できます。シンボルに関連付けられています。これは次のような定義に対して機能します
f[x_, y_] := x + y
または
g[3] = 72 * a;
次のようなエキゾチックなものには機能しません
h[a_][b] = "gribble";
しかし、ほとんどの人は、とにかく関数を定義しているとは考えません。関数定義の存在を確認したい場合は、名前を式に変換する必要があります(実行するときに Hold
でラップされていることを確認してください!)。以下は、 DownValues
と SubValues
の両方をチェックするかなり堅牢な関数です。
functionNameQ[name_String] :=
With[{ hSymbol = ToExpression[name, InputForm, Hold] },
MatchQ[hSymbol, Hold[_Symbol]] &&
((DownValues @@ hName) =!= {} || (SubValues @@ hName) =!= {})];
defined[str_] := Not[ToString[FullDefinition[str]] === ""]