【发布时间】:2011-06-03 17:02:17
【问题描述】:
有没有简单的方法来检查 x 是否有定义?我需要一个功能
f,f[_] 或 f[_][_] 的形式,如果有定义则返回 True
具体来说,我使用 f[x]=b 和 g[x][y]=z 之类的结构来存储东西,我需要检查 f[x] 是否对某些中的每个 x 都有定义列表,如果 g[x][y] 对某些值集中的每个 x,y 都有定义
【问题讨论】:
有没有简单的方法来检查 x 是否有定义?我需要一个功能
f,f[_] 或 f[_][_] 的形式,如果有定义则返回 True
具体来说,我使用 f[x]=b 和 g[x][y]=z 之类的结构来存储东西,我需要检查 f[x] 是否对某些中的每个 x 都有定义列表,如果 g[x][y] 对某些值集中的每个 x,y 都有定义
【问题讨论】:
预期用途是什么?
【讨论】:
DownValues 帮助我检查了一个函数是否已定义,ValueQ 对此不起作用——或者如果调用为 ValueQ[myFunc[x]] 将评估该函数。
如果我理解正确,我认为函数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]]}
如果您删除 ValueQ 的 ReadProtected 属性并查看代码,您会明白原因 - 代码非常简单,并且仅对 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*)
【讨论】: