Message Boards Message Boards

1
|
9146 Views
|
12 Replies
|
9 Total Likes
View groups...
Share
Share this post:

Avoid unexpected behavior with ValueQ?

Dear members of the community I trying to improve an algorithm where data is stored in a hash table and where ValueQ is going to be used to operate only over defined elements. The case can be easily exemplified as follows:

  1. Let us tabulate some data

    Do[f[i] = i, {i, 1, 10, 2}]
    

clearly if one explores these definition through ValueQ, we obtain 'True' for

    ValueQ[f[1]]

and 'False' for

    ValueQ[f[2]]

However, the above do not seem to work within a loop, for instance

Table[If[ValueQ[f[i]], f[i], "No value"], {i, 10}]

In this case the output is {1, f[2], 3, f[4], 5, f[6], 7, f[8], 9, f[10]} but I was expecting this to be the following {1,"No value",3,"No value",.....} It seems that ValueQ[] always returns 'True' as an output I am rather confused with this result and I will appreciate any help. Regards Jesus Rico

12 Replies

Sander Huisman, Tanks, this is also a good implementation. I tend to think that pure functions are the fastest way to proceed when writing algorithms... but that is more than a feeling than anything else.

It will keep in mind this alternative way of working things out.

Thanks again

Jesus

As a side note: you could use an association to store your data:

Associations provide generalizations of symbolically indexed lists, associative arrays, dictionaries, hashmaps, structs, and a variety of other powerful data structures.

Then when you ask for a value that is not yet defined it will return missing:

hash = <||>;
Do[AssociateTo[hash, i -> i], {i, 1, 10, 2}]
Table[If[MissingQ[hash[i]], "No value", hash[i]], {i, 10}]

returns the correct result. This might even be a faster and more flexible solution.

POSTED BY: Sander Huisman

Excellent - many thanks, Sander!

(As an off topic remark concerning readability: See this discussion).

Posted 8 years ago

This is not a bug.

ValueQ is HoldAll, meaning the expression that is evaluated is ValueQ[f[i]], which becomes f[1], f[2], etc, which is obviously different from f[i]. (Recall that Table is a dynamic scoping construct, effectively using Block[{i=val},...] to evaluate the expression in its first argument for each value val that i takes). What you want is this:

In[29]:= Table[ With[{i = j}, If[ValueQ[f[i]], f[i], "No value"]], {j, 10}]
Out[29]= {1, "No value", 3, "No value", 5, "No value", 7, "No value", 9, "No value"}

Because With is a lexical scoping construct, which rewrites each instance of i with its value j prior to beginning to evaluate its second argument, this yields the evaluation of ValueQ[f[1]], ValueQ[f[2],] ... and your expected result. An alternative approach is to use Map with a pure function, which against inserts the value of the variable prior to the start of valuation:

In[30]:= If[ValueQ[f[#]], f[#], "No value"] & /@ Range[10]
Out[30]= {1, "No value", 3, "No value", 5, "No value", 7, "No value", 9, "No value"}
POSTED BY: Itai Seggev

Thanks Guys

Your answers are all useful. Itai-- Thanks for your very precise explanation. It is educational. I am going to adopt 'map with a pure function' since it seems to me that it is more straightforward and easier to read.

Regards

Jesus

Thanks for the explanation. I find writing these things using Map easier anyhow. That's why I also suggested above to use Map over Table in such example.

I didn't know about the nested behaviour of these scopic constructs, thanks for showing.

POSTED BY: Sander Huisman

I noticed the same thing--either way, it is a bug.

Moderators, please take note and pass on to the developers.

POSTED BY: David Reiss

This is not a bug. ValueQ is a funny function and it's good to be aware what it actually does before attempting to use it. To say that it checks if the expression has a value is inaccurate and can be misleading.

ValueQ[x] will check the OwnValues of x is x is a symbol.

But in all other cases ValueQ simply evaluates its argument and checks if it has evaluated to something that differs from the original.

You can check the implementation:

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

This of course is problematic in so many ways, e.g. think about what happens if evaluating expr has side effects.

But this behaviour is clearly documented, see under Details in the doc page.

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

There's a lot of discussion of ValueQ on StackExchange here:

POSTED BY: Szabolcs Horvát

Hi Jesus,

This is indeed some 'unexpected' behavior, as an alternative you can use (2 methods):

If[ValueQ[f[#]], f[#], "No value"] & /@ Range[10]
Table[If[Head[f[i]] =!= f, f[i], "No value"], {i, 10}]

I think it has to do with ValueQ[f[i]] that is converted to:

!Hold[Evaluate[f[i]]]===Hold[f[i]]

I think the Hold interferes with Table, but I'm not 100% sure what the exact problem is. Reading a 'trace' is never easy:

Trace[Table[If[ValueQ[f[i]], f[i], "No value"], {i, 2}]]

gives:

{Table[If[ValueQ[f[i]],f[i],No value],{i,2}],{{ValueQ[f[i]],!Hold[Evaluate[f[i]]]===Hold[f[i]],{{{{i,1},f[1],1},Hold[1]},Hold[1]===Hold[f[i]],False},!False,True},If[True,f[i],No value],f[i],{i,1},f[1],1},{{ValueQ[f[i]],!Hold[Evaluate[f[i]]]===Hold[f[i]],{{{{i,2},f[2]},Hold[f[2]]},Hold[f[2]]===Hold[f[i]],False},!False,True},If[True,f[i],No value],f[i],{i,2},f[2]},{1,f[2]}}
POSTED BY: Sander Huisman

In principle - according to Sanders remark - Trace is already perfectly showing what is going on. One can improve the readability simply by wrapping the output in a "repeated frame" like so:

Framed //@ Trace[Table[If[ValueQ[f[i]], f[i], "No value"], {i, 2}]]

Regards -- Henrik

POSTED BY: Henrik Schachner

That's a real neat tip! Thanks! A small improvement is to color the frames differently:

Framed[#, FrameStyle -> RandomColor[]] & //@

Thanks Henrik!

POSTED BY: Sander Huisman

Excellent - many thanks, Sander!

(As an off topic remark concerning readability: See this discussion).

POSTED BY: Henrik Schachner
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract