Group Abstract Group Abstract

Message Boards Message Boards

1
|
11.8K 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

Excellent - many thanks, Sander!

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

Excellent - many thanks, Sander!

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

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

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

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

POSTED BY: Sander Huisman
POSTED BY: Szabolcs Horvát

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

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

Posted 9 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

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

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
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard