I think so. I wanted your opinion because I am not thinking very clearly right now.
I am trying to think of a way around that problem, and this is what has come to mind:
If we check the Depth of the Unevaluted[expr] and then use that for TraceDepth (or rather depth-1), do you believe this addresses the problem or merely obscures it?
For reference and testing:
SetAttributes[valueQx, HoldAll]
valueQx[expr_] :=
Module[{P, R = False, d = Depth@Unevaluated@expr},
P = (P = Return[R = True, TraceScan] &) &;
TraceScan[P, expr, TraceDepth -> Max[1, d - 1]];
R
]
@MrWizard I don't completely understand the relationship between Trace and TraceScan. Consider for example Reap@TraceScan[Sow, f[1,2+3]] and Trace[f[1,2+3]]. Why do they return a different set of expressions?
Without revisiting documentation or digging deeper TraceScan is more complete; I believe Trace leaves out steps. Perhaps these can be recovered with the options like TraceInternal. I cannot recall.
I am curious to know how this relates to your analysis. :-)
Of course Trace gathers into nested lists while TraceScan does not. That caused me some trouble until I noticed TraceLevel[] and TraceDepth. What are you thinking?
@MrWizard I'm sorry, I realize I really don't understand Trace ... for example, what's wrong with using a TraceDepth of Infinity? Just give me an example where valueQ would fail with Infinity but works with 1
That's exactly what valueQ2 is doing. The issue is the evaluation that takes place even with simple expressions, thereby triggering a result of "True" on, for example: "a" + "b"
You can see from TracePrint["a" + "b"]; that evaluation takes place, even though no rule is found that transforms the entire expression.
Originally I was only thinking about expressions like f[x] and maybe f[x,y]. For these your solution works well, at least as long as they don't have any special attributes
I now realize that it's not so simple to generalize the concept to general exception
I originally said that it should return True if the expression would change during evaluation
this seems rather clear (though it's debatable if it's the same as "having a value"), and b+a does indeed change during evaluation
then we have all the different non-standard evaluations
I think valueQ1 still comes the closest to that definition even though it leaks (but less than the built-in). On the other hand I am more and more seeing the value in Leonid's approach, even though the result diverges from ValueQ.
@MrWizard let's postpone this, I'm feeling really broken today :-( I should not have started with the discussion at all. Let's continue another time if you don't mind.