1
|
9723 Views
|
12 Replies
|
9 Total Likes
View groups...
Share
GROUPS:

# Avoid unexpected behavior with ValueQ?

Posted 8 years ago
 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: 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
Sort By:
Posted 8 years ago
 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 againJesus
Posted 8 years ago
 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 8 years ago
 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 8 years ago
 Thanks GuysYour 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.RegardsJesus
Posted 8 years ago
 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 8 years ago
 I noticed the same thing--either way, it is a bug.Moderators, please take note and pass on to the developers.
Posted 8 years ago
 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 8 years ago
 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 8 years ago
 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 8 years ago
 That's a real neat tip! Thanks! A small improvement is to color the frames differently: Framed[#, FrameStyle -> RandomColor[]] & //@ Thanks Henrik!
Posted 8 years ago
 Excellent - many thanks, Sander!(As an off topic remark concerning readability: See this discussion).