3 replaced http://mathematica.stackexchange.com/ with https://mathematica.stackexchange.com/
source | link

I learned from @halirutan's answer in ValueQ returns false positive for one argument type onlyValueQ returns false positive for one argument type only that ValueQ simply tests whether an expression is equal to running Evaluate on itself, i.e.

I learned from @halirutan's answer in ValueQ returns false positive for one argument type only that ValueQ simply tests whether an expression is equal to running Evaluate on itself, i.e.

I learned from @halirutan's answer in ValueQ returns false positive for one argument type only that ValueQ simply tests whether an expression is equal to running Evaluate on itself, i.e.

2 deleted 70 characters in body
source | link

Note: The possible duplicate is no longer an actual duplicate.

Note: The possible duplicate is no longer an actual duplicate.

1
source | link

Note: The possible duplicate is no longer an actual duplicate.

tl;dr

Use this modified valueQ function.

SetAttributes[valueQ, {HoldFirst}];
valueQ[h_[args__]] :=
    With[{eval = args},
       ! Hold[Evaluate[h[eval]]] === Hold[h[eval]]
    ];

How ValueQ works.

I learned from @halirutan's answer in ValueQ returns false positive for one argument type only that ValueQ simply tests whether an expression is equal to running Evaluate on itself, i.e.

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

If it does match up, then this non-transformation indicates non-value, and vice versa.

The issue with variables (DownValues).

So here's what was happening. Let's take @halirutan's example:

table[a] = foo;
table[b] = bar;
table[c] = baz;
{ValueQ[table[a]], ValueQ[table[d]]}

(* {True, False} *)

This is correct, of course—a is a key, d is not. Now, let's introduce keyA and keyD:

keyA = a;
keyD = d;
{ValueQ[table[keyA]], ValueQ[table[keyD]]}

(* {True, True} *)

Wait, but why? Well, let's plug in our expression into @halirutan's exposed ValueQ expression, i.e.

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

For the keyA case, here are the evaluated and non-evaluated sides, separately:

{Hold[Evaluate[table[keyA]]], Hold[table[keyA]]}

(* {Hold[foo], Hold[table[keyA]]} *)

So, you see, table[keyA] is fully evaluated to foo on the LHS (as expected), while table[keyA] stays as is on the RHS (as expected), and the fact that they're different means ValueQ should return True, i.e. the expression indeed "has a value," transforming when evaluated.

Now, let's do the same for keyD:

{Hold[Evaluate[table[keyD]]], Hold[table[keyD]]}

(* {Hold[table[d]], Hold[table[keyD]]} *)

Here we see the issue. Even though table[d] doesn't have a value, the evaluation of keyD to d is still considered a transformation. Therefore when compared to the RHS, which has remained table[keyD], the difference leads to ValueQ returning True.

Evaluating both sides.

This was the first thing I tried, e.g.

{ValueQ[Evaluate[table[a]]], ValueQ[Evaluate[table[d]]]}

(* {False, False} *)

But now that we know how ValueQ works, it becomes a silly solution. By Evaluateing the expression prior to passing it into ValueQ, we guarantee that it will match during the comparison, since the very thing that ValueQ does is Evaluate the expression, making ValueQ return False always (i.e. the expression didn't transform, so it "has no value").

Finally, the solution.

@halirutan's two answers actually cover a more sophisticated problem than mine, but also different enough that neither cover the transformation of variables (i.e. symbols with DownValues).

It was pretty easy to come up with a solution, however. We simply need the argument (the "key" expression) to be evaluated before being passed into ValueQ:

SetAttributes[valueQ, {HoldFirst}];
valueQ[h_[args__]] :=
    With[{eval = args},
       ! Hold[Evaluate[h[eval]]] === Hold[h[eval]]
    ];

This appears to work fine:

{valueQ[table[keyA]], valueQ[table[keyD]]}

(* {True, False} *)