Эквивалент определенного в Mathematica

Мне нужна функция, которая принимает имя символа в виде строки и возвращает значение, определяющее, уже ли этот символ определен. Функция 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: спасибо Pillsy за указание на необходимость проверки как DownValues, так и SubValues.


person dreeves    schedule 18.09.2009    source источник


Ответы (4)


Я думаю, что имена должны помочь:

Names["string"] дает список имен символов, соответствующих строке.

Если Names["foo"] возвращает {}, то для foo не должно быть определений, иначе он должен возвращать {"foo"}. Таким образом, ваша функция «определена» может быть выполнена как:

defined[str_] := Names[str] != {}

По крайней мере, для символов, потому что это не работает для «7», поскольку 7 не является символом. Вы можете обработать этот случай отдельно, например, с помощью NumberQ.

Кроме того, вы можете использовать Symbol для создания символа из строки (полезно для автоматического создания символов) и Definition для проверки определений символа.

Symbol["name"] ссылается на символ с указанным именем.

Определение[символ] печатается как определения, данные для символа.

EDIT: Лучше, чем смотреть, что возвращает Names, NameQ["name"] сообщает вам, существует ли заданное имя. Тем не менее, он не говорит вам, имеет ли символ явное определение, просто он упоминается.

person Joren    schedule 18.09.2009
comment
О, классно! Однако это не работает для имен [7]. Кроме того, если вы хотя бы упомянете символ x, то Names[x] укажет, что он определен, даже если на самом деле у него нет определения. - person dreeves; 18.09.2009
comment
Ты прав. Я не уверен, есть ли способ узнать, имеет ли символ явное определение или он только упоминается. Definition[foo] говорит вам об этом, но я думаю, что его нельзя использовать автоматически. - person Joren; 19.09.2009

Я собрал это вместе, что, кажется, работает:

defined[s_] := ToExpression["ValueQ[" <> s <> "]"] || 
               Head@ToExpression[s] =!= Symbol || 
               ToExpression["Attributes[" <> s <> "]"] =!= {} ||
               ToExpression["DownValues[" <> s <> "]"] =!= {} ||
               ToExpression["SubValues[" <> s <> "]"] =!= {}

Надеюсь, есть более красивое решение.

PS: спасибо Pillsy за указание на необходимость проверки как DownValues, так и SubValues.

person dreeves    schedule 18.09.2009
comment
если я хочу быть динамичным, как я могу преобразовать Cos в Cos? - person Rainb; 22.04.2020

Вы можете использовать DownValues, чтобы увидеть, есть ли у вас «функции», связанные с символом. Это будет работать для таких определений, как

f[x_, y_] := x + y

or

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) =!= {})];
person Pillsy    schedule 19.09.2009

person    schedule
comment
У этого решения есть побочные эффекты, оно будет оценивать функции. например f[x_] := Print[x], defined[f["Hello"]]. Взгляните на это. - person Rohit Namjoshi; 30.12.2018
comment
@Rohit: это проблема с проблемой остановки, а не с моим решением. Предположим, у вас есть f[x_] := Modue[{}, If[veryComplicatedConditionWhichNobodyKnowsWillEvenFinishComputingBeforeEternityCome, Sin, somethingUndefined], и вы хотите знать, определен ли f[someX], тогда вы хотите знать, является ли результат Sin или somethingUndefined, и если вы можете сделать это (в общем случае) без фактического вызова veryComplicatedConditionWhichNobodyKnowsWillEvenFinishComputingBeforeEternityCome, то вы можете решить проблему остановки. - person mathheadinclouds; 01.01.2019