Проверка, определен ли символ - PullRequest
18 голосов
/ 05 января 2011

Есть ли простой способ проверить, есть ли определение для х? Мне нужна функция, которая принимает что-то в форме f, f[_] или f[_][_] и возвращает True, если для него есть определение

Чтобы быть по-настоящему конкретным, я храню вещи, используя такие конструкции, как f [x] = b и g [x] [y] = z, и мне нужно проверить, имеет ли f [x] определение для каждого x в некоторых list и если g [x] [y] имеет определение для каждого x, y в некотором наборе значений

Ответы [ 4 ]

22 голосов
/ 07 января 2011

На самом деле, функция ValueQ не является невинной, поскольку она пропускает оценку для кода с побочными эффектами. Примеры:

ClearAll[f, g]; 
f[x_] := Print[x]; 
g[x_][0] := Print[x];
{ValueQ[f[1]],ValueQ[g[2][0]]}

Если вы удалите атрибут ReadProtected из ValueQ и посмотрите на код, вы поймете, почему - код очень прост и выполняет достойную работу только для OwnValues. Вот более сложная версия, которую я разработал, чтобы избежать этой проблемы (вы можете проверить, что, по крайней мере для приведенных выше примеров, она не дает утечки):

ClearAll[symbolicHead];
SetAttributes[symbolicHead, HoldAllComplete];
symbolicHead[f_Symbol[___]] := f;
symbolicHead[f_[___]] := symbolicHead[f];
symbolicHead[f_] := Head[Unevaluated[f]];

ClearAll[partialEval];
SetAttributes[partialEval, HoldAllComplete];
partialEval[a_Symbol] /; OwnValues[a] =!= {} := 
   Unevaluated[partialEval[a]] /. OwnValues[a];

partialEval[a : f_Symbol[___]] /; DownValues[f] =!= {} :=
   With[{dv = DownValues[f]},
      With[{eval = Hold[partialEval[a]] /. dv},
         ReleaseHold[eval] /; 
           (First[Extract[eval, {{1, 1}}, HoldComplete]] =!= 
           HoldComplete[a])]];

partialEval[a_] :=
   With[{sub = SubValues[Evaluate[symbolicHead[a]]]},
      With[{eval = Hold[partialEval[a]] /. sub},
         ReleaseHold[eval] /; 
           (First[Extract[eval, {{1, 1}}, HoldComplete]] =!= 
           HoldComplete[a])]];

ClearAll[valueQ];
SetAttributes[valueQ, HoldAllComplete];
valueQ[expr_] := partialEval[expr] =!= Unevaluated[partialEval[expr]];

Это также не полный процесс, поскольку он не учитывает значения UpValues, NValues ​​и FormatValues, но этого, по-видимому, достаточно для ваших заявленных потребностей, а также, возможно, правила для этих трех дополнительных случаев также могут быть добавлены к тому же самому линии, как указано выше.

16 голосов
/ 05 января 2011

Если я правильно понял, я думаю, что функция ValueQ - это то, что вы ищете.Он вернет истину, если переменная или функция была определена, и ложь, если она не была определена.

Подробнее на http://reference.wolfram.com/mathematica/ref/ValueQ.html

1 голос
/ 01 октября 2013

Вот хорошее, простое решение, которое работает, если рассматриваемый объект имеет достаточную внутреннюю структуру.

Вы можете использовать

Length[variable]

, чтобы определить, было ли назначено variable для чего-либо с более чем одной частью. Таким образом:

Remove[variable]
Length[variable]
(*---> 0*)
variable={1,2,3};
Length[variable]
(*---> 3*)

Затем вы можете использовать Length[variable]>0, чтобы получить True в последнем случае.

Однако это не получится, если есть вероятность, что variable будет присвоено атомарному значению, например одной строке или числу:

variable=1
Length[variable]
(*---> 0*)
1 голос
/ 05 января 2011
  • Для символов в System`, проверьте SyntaxInformation для опции ArgumentsPattern.
  • Для других символов, проверьте DownValues, UpValues, SubValues ​​и т.д ...предполагаемое использование?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...