Ответ 1
Если я правильно понял, я думаю, что функция ValueQ
- это то, что вы ищете. Он вернет true, если определена переменная или функция, а false, если она не определена.
Подробнее на http://reference.wolfram.com/mathematica/ref/ValueQ.html
Есть ли простой способ проверить, существует ли определение для x? Мне нужна функция, которая принимает
что-то вроде формы f
, f[_]
или f[_][_]
и возвращает True
, если есть определение для него
Чтобы быть конкретным, я храню вещи, используя такие конструкции, как f [x] = b и g [x] [y] = z, и мне нужно проверить, имеет ли f [x] определение для каждого x в некотором и если g [x] [y] имеет определение для каждого x, y в некотором наборе значений
Если я правильно понял, я думаю, что функция ValueQ
- это то, что вы ищете. Он вернет true, если определена переменная или функция, а false, если она не определена.
Подробнее на http://reference.wolfram.com/mathematica/ref/ValueQ.html
На самом деле функция 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, но этого, кажется, достаточно для ваших заявленных потребностей, а также правила для этих трех дополнительных случаев могут быть также добавлены по тому же как указано выше.
Какое намеренное использование?
Здесь хорошее, простое решение, которое работает, если объект, о котором идет речь, имеет достаточную внутреннюю структуру.
Вы можете использовать
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*)