Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Mathematica has a built-in function ValueQ. Quoting the docs,

ValueQ[expr] gives True if a value has been defined for expr, and gives False otherwise.

...

ValueQ gives False only if expr would not change if it were to be entered as Mathematica input.

This works nicely with symbols that only have OwnValues:

x = Print["boo!"]
ValueQ[x]

(* ==> True *)

It doesn't work so nicely with functions, though:

f[x_] := Print[x]
ValueQ[f[1]]

(*
     1
 ==> True
*)

This gives True, but also evaluates f[1] completely, printing 1. This is clearly dangerous, and it is important to be aware of this. Unfortunately, the docs make no mention of this under the "Possible Issues" section!

Why this happens is clear if we look at the implementation of ValueQ for non-symbols:

ValueQ[expr_] := ! Hold[Evaluate[expr]] === Hold[expr]

Question: Is it possible to implement a more robust version of ValueQ, which does not evaluate its argument in an unexpected an possibly dangerous way?

share|improve this question
    
This is especially weird since ValueQ has the atttribute HoldAll. Maybe you discovered a bug? –  David Feb 8 '12 at 4:39
6  
@David HoldAll attribute only says what will happen to the function's arguments before they are passed to the function, but nothing about how the function itself evaluates them. A situation when function is not supposed to evaluate arguments passed to it but does that nonetheless, is called evaluation leak, and is something to watch out for when you develop HoldAll etc functions. For the case at hand, this was discovered before, perhaps more than once, e.g. here. –  Leonid Shifrin Feb 8 '12 at 6:00
    
There are several ways to handle the meaning of ValueQ, as Leonid and I have been discussing. I deleted my answer until I have time to consider all this and expand/revise accordingly. –  Mr.Wizard Feb 8 '12 at 9:24
    
@Leonid I am dissatisfied with the function in its current state; it's just too weird to get True for Hold[2] or "a" + "b" or x[1][2] (where x is undefined). I am exploring another possibility now. –  Mr.Wizard Feb 8 '12 at 9:56
    
@Mr. Wizard I see. –  Leonid Shifrin Feb 8 '12 at 10:03

2 Answers 2

Preamble

This has been discussed before, and this problem was also identified and partially addressed in the same question. I will use a slightly simpler implementation which also covers UpValues. It is probably not complete either, but it covers many common cases of interest.

Implementation

Here is the code:

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

ClearAll[valueQ];
SetAttributes[valueQ, HoldAllComplete];
valueQ[a_Symbol] /; OwnValues[a] =!= {} :=
    With[{result = (# =!= (# /. OwnValues[a])) &[HoldComplete[a]]},
       result /; result];

valueQ[a : f_Symbol[___]] /; DownValues[f] =!= {} :=
    With[{result = (# =!= (# /. DownValues[f])) &@HoldComplete[a]},
       result /; result];

valueQ[a_] :=
    With[{sub = SubValues[Evaluate[symbolicHead[a]]]},
      With[{result  = (# =!= (# /. sub)) &[HoldComplete[a]]},
          result /; result] /; sub =!= {}
    ];

valueQ[a_] :=
   With[{upsyms  =
       Flatten@Cases[Unevaluated[a], s_Symbol :> UpValues[s], 1, Heads -> True]},
          With[{result  = (# =!= (# /. upsyms)) &[HoldComplete[a]]},
             result /; result] /; upsyms =!= {}
   ];

valueQ[_] := False;

Symbolic heads are further discussed in this answer. The order of definitions is important, and roughly corresponds to the order of steps applying those global rules, in the main evaluation sequence.

Examples

a := Print["*"];
b[1] := Print["*"];
c[1][4] := Print["*"];
d /: f[x_Integer, d, y_Integer] := Print["*"];

valueQ /@ Unevaluated[{a, b[1], c[1][4], f[1, d, 2]}]

(*
  ==> {True, True, True, True}
*)

Limitations

I did not include the NValues (this can be done, but the question is whether we really want to do that). This seems to pretty much exhaust the set of things we can do without really evaluating an expression in question. In certain cases, the results will be different from ValueQ, for example:

{valueQ[N[Pi]],ValueQ[N[Pi]]}

(*
  ==> {False,True}
*)

Summary

The code above was not meant to be absolutely complete, and probably can not be, since not everything is exposed to the top-level / end user. But it is hoped that it covers many cases of interest, and can be further extended to cover some that it misses currently. Note that, since internal global rules are not available at the top-level, valueQ is mostly limited to user-defined or top-level functions and variables. If one wants to include system symbols with internal rules, I don't see other ways than allowing the expression to evaluate.

This may also explain (to some extent), why built-in ValueQ was written the way it was - to also cover the system symbols and be general. On a deeper level, this seems to reflect that the separation between internal and top-level rules is rather artificial and sometimes flies in the face of the core language semantics, particularly when one wants to write some general functions related to introspection, such as ValueQ.

share|improve this answer
    
This is probably obvious, but here is another case where valueQ and ValueQ differ: {valueQ@{1 + 1}, ValueQ@{1 + 1}}. Overall I think valueQ is much more useful. –  Ajasja Apr 23 '13 at 14:23
1  
@Ajasja Good point, thanks. Generally, picking one over another is a hard question, because there is no direct mapping between Mathematica evaluation sequence and our expectations of usefulness in this or that situation (evaluation sequence usually contains steps which we consider trivial and others we consider important, but from the system's viewpoint all steps have the same degree of importance. So, filtering out "trivial" evaluations is to a large degree a subjective matter). That said, I agree that more often than not I find ValueQ to not be appropriate for the task, unlike valueQ. –  Leonid Shifrin Apr 23 '13 at 14:55
    
Interestingly, under v8 and v9, valueQ /@ Unevaluated[{a, b[1], c[1][5], f[1, d, 2]}] returns {True, True, False, True} instead of four True-s. Did I miss something? –  István Zachar Jun 11 '13 at 8:27
    
@IstvánZachar Thanks, you spotted a typo. Should have been c[1][4]. It is unclear to me how this leaked into the answer, usually I copy the output directly from Mathematica. Will edit now. –  Leonid Shifrin Jun 11 '13 at 9:51
    
Ah, ok, I assumed that it was deliberate to call with a different argument than in the definition. –  István Zachar Jun 11 '13 at 11:54

Using the core of my new step function:

SetAttributes[valueQ1, HoldAll]

valueQ1[expr_] :=
 Module[{P, R = False},
   P = (P = Return[R = True, TraceScan] &) &;
   TraceScan[P, expr, TraceDepth -> 1];
   R 
 ]

SetAttributes[valueQ2, HoldAll]

valueQ2[expr_] :=
 Module[{P, R = False},
   P = (P = Return[R = True, TraceScan] &) &;
   TraceScan[P, expr];
   R 
 ]

SetAttributes[valueQ3, HoldAll]

valueQ3[expr_] :=
  Block[{Print},
    TraceScan[
      Null &, expr, _,
      If[# =!= HoldForm[#2], Return[True, TraceScan]] &
    ] // TrueQ
  ]

Long overdue update.

valueQ1 is my proposal for an alternative to ValueQ which leaks far less often. In most cases it returns the same answer that ValueQ does. It gives True if the entire expression is transformed in the course of evaluation.

valueQ2 is a trigger-happy version of Q1 that returns True if any evaluation takes place for the given expression. Leonid favors this one as being the most "pure" within Mathematica's framework, but it also makes for a lot of (arguably) false-positives.

valueQ3 is an attempt to get behavior closer to ValueQ (than Q1), and no leaks, but it may not be robust. The purpose of Blocking Print is NOT to hide the leaks (i below is used to check this), but a work-around because Print caused the method to fail; it is unknown to me what other function calls would also cause failure.

Here is a table of results for these functions compared to ValueQ:

ClearAll[a, b, c, d, f, g, gg, x];
i = 0;
a := Print["*a"];
b[1] := (i++; Print["*b"])
c[1][4] := (i++; Print["*c"])
d /: f[x_Integer, d, y_Integer] := (i++; Print["*d"])
gg[x_] := (i++; Print["*gg"]; False)
g[x_] /; gg[x] := x^2
x = 1;

Mathematica graphics

Results in red are tests that leaked.

share|improve this answer
1  
Trace and friends have to evaluate the expression being traced, if I am not mistaken. –  Leonid Shifrin Feb 8 '12 at 6:17
    
No I did not yet - my comment was just based on the general considerations. I will look into it. –  Leonid Shifrin Feb 8 '12 at 6:29
    
Yes. For example, here: valueQAlt[{b[1]}] - it leaks evaluation. –  Leonid Shifrin Feb 8 '12 at 6:32
    
This is not the point. The point is that we should be able to feed any expression into valueQ, and be sure that it won't be evaluated. Imagine using valueQ inside e.g. Cases, something like Cases[Unevaluated[expr],sub_/;valueQ[sub]:>HoldComplete[sub],Infinity]. In other words, at least in my interpretation, this question is in the first place about making valueQ with a well-defined and general evaluation semantics. –  Leonid Shifrin Feb 8 '12 at 6:41
1  
@Rojo Thanks. Slowly I am forming ideas about the utility of these functions. Leonid's is more like a "HasDefinitionQ" than ValueQ. My valueQ1 is similar to ValueQ but leaks less (though it still leaks). valueQ2 is really more like a "NotInertQ". The third function is experimental. I see why something like valueQ3[x = 8] leaks (while valueQ3[x = 2 + 2] doesn't), and I am not confident that it can be made to work. I think that I would have to compile a list of built-in "verbs" that specifically take action such as Set and Print and catch those before evaluation. –  Mr.Wizard Feb 9 '12 at 9:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.