2
$\begingroup$

TL;DR: I have a series of variables $x_1, x_2, x_3, \dots$ which to which I assign values inside a loop. However, when I use ValueQ to determine which values I've already assigned, the results don't appear to make much sense.

Minimal example: Code:

Clear[x]; For[i = 1, i < 4, i = i + 1, x[i] = i; Print[i, ": ", ValueQ[x[i]], " ", ValueQ [x[i + 1]], " ", ValueQ [x[i + 10]] , " ", ValueQ[x[2]]]] 

Output:

1: True True True False 2: True True True True 3: True True True True 

Explanation: In $i$-th iteration of the loop, I assign the value to x[i]. Hence, in $i$-th iteration the values x[1], x[2], ..., x[i] are defined, but x[i+1], x[i+2], ... are not. However, when I try to check if x[j] are defined, Mathematica tells me that: 1) x[i] is defined, as expected; 2) x[i+1] is defined, although it is not yet defined; 3) x[i+10] is defined, although it is never defined at all; 4) x[2] is defined if and only if $i \geq 2$, as expected.

Motivation: In the application I have in mind, I'm computing values $x_i$ in a somewhat haphazard order. It so happens that to compute $x_i$ it is useful to know $x_j$ where $j$ is a function of $i$ (a non-trivial one). At the time $x_i$ is computed, I would like to check if $x_j$ has already been computed, and use its value if it has (if it has not, then I need to compute $x_i$ in a more time-consuming way). However, when I try to implement this using ValueQ, I get the unexpected behaviour described above.

Question: How does this behaviour arise, and how can I change the above code to make it work?

$\endgroup$
9
  • $\begingroup$ "ValueQ gives False only if expr would not change if it were to be entered as Wolfram Language input. " - x[i + 10] would change, becoming x[10+i] $\endgroup$ Commented Feb 5, 2018 at 21:02
  • $\begingroup$ For your application here, use a smarter test function, like IntegerQ or NumericQ $\endgroup$ Commented Feb 5, 2018 at 21:19
  • $\begingroup$ @JasonB Actually, it would change also because i has a value within the loop. $\endgroup$ Commented Feb 5, 2018 at 21:21
  • $\begingroup$ From my experience, lists work much faster than constructions like x[i]. And they have no such weird artifacts. $\endgroup$ Commented Feb 5, 2018 at 21:28
  • 1
    $\begingroup$ Sounds like you should be using memoization? $\endgroup$ Commented Feb 5, 2018 at 21:48

1 Answer 1

4
$\begingroup$

since x[1+1] evaluates (at least) to x[2], ValueQ returns True as it is already different than the input.

You don't have to check if you already calculated x for e.g. 2. You can use memoization:

 x[n_]:=x[n] = ... 

So once e.g. x[5] is called, each subsequent x[5] will not require recomputation.

$\endgroup$
3
  • $\begingroup$ Thank you for explaining where the issue comes from. However, in this particular case, momoization is not the solution: I specifically need to check if x[i] (say) is defined, and do one of two different things depending on the outcome (i.e. if I learn that I could speed up computing x[1] by knowing the value of x[101] but I haven't yet computed x[101], I don't want to compute x[101] but rather I want to run a completely different routine). $\endgroup$ Commented Feb 6, 2018 at 16:54
  • 1
    $\begingroup$ @JakubKonieczny I see, without details I can only suggest to check MatchQ[x[i], _x]. $\endgroup$ Commented Feb 6, 2018 at 17:35
  • $\begingroup$ @JakubKonieczny or ValueQ[x[#]]&[1+1] $\endgroup$ Commented Feb 12, 2018 at 12:58

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.