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$
  • $\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$ – Jason B. Feb 5 '18 at 21:02
  • $\begingroup$ For your application here, use a smarter test function, like IntegerQ or NumericQ $\endgroup$ – Jason B. Feb 5 '18 at 21:19
  • $\begingroup$ @JasonB Actually, it would change also because i has a value within the loop. $\endgroup$ – Szabolcs Feb 5 '18 at 21:21
  • $\begingroup$ From my experience, lists work much faster than constructions like x[i]. And they have no such weird artifacts. $\endgroup$ – Vsevolod A. Feb 5 '18 at 21:28
  • 1
    $\begingroup$ Sounds like you should be using memoization? $\endgroup$ – Carl Woll Feb 5 '18 at 21:48
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$
  • $\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$ – Jakub Konieczny Feb 6 '18 at 16:54
  • 1
    $\begingroup$ @JakubKonieczny I see, without details I can only suggest to check MatchQ[x[i], _x]. $\endgroup$ – Kuba Feb 6 '18 at 17:35
  • $\begingroup$ @JakubKonieczny or ValueQ[x[#]]&[1+1] $\endgroup$ – Kuba Feb 12 '18 at 12:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.