Checking if a symbol is defined

2019-01-22 13:58发布

问题:

Is there an easy way to check if there's a definition for x? I need a function that takes something of the form f,f[_] or f[_][_] and returns True if there's a definition for it

To be really concrete, I'm storing things using constructs like f[x]=b, and g[x][y]=z and I need to check if f[x] has definition for every x in some list and if g[x][y] has a definition for every x,y in some set of values

回答1:

If I understood correctly I think the function ValueQ is what you are looking for. It will return true if a variable or a function has been defined and false if it has not been defined.

Read more at http://reference.wolfram.com/mathematica/ref/ValueQ.html



回答2:

Actually, the ValueQ function is not innocent, since it leaks evaluation for code with side effects. Examples:

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

If you remove the ReadProtected Attribute of ValueQ and look at the code, you will see why - the code is very simplistic and does a decent job for OwnValues only. Here is a more complex version which I developed to avoid this problem (you can test that, at least for the examples above, it does not leak evaluation):

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]];

This is not complete either, since it does not account for UpValues, NValues, and FormatValues, but this seems to be enough for your stated needs, and also, rules for these three extra cases can perhaps also be added along the same lines as above.



回答3:

  • For symbols in System`, check SyntaxInformation for a ArgumentsPattern option.
  • For other symbols, check DownValues, UpValues, SubValues, etc...

What's the intended use?



回答4:

Here's a nice, simple solution which works if the object in question has enough internal structure.

You can use

Length[variable]

to detect whether variable has been assigned to something with more than one part. Thus:

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

You can then use Length[variable]>0 to get True in the latter case.

This fails, though, if there's a chance that variable be assigned to an atomic value, such as a single string or number:

variable=1
Length[variable]
(*---> 0*)