4
$\begingroup$

This question already has an answer here:

I am trying to create a list of functions in a loop, using a list of parameters as input to the functions. However, after assigning the each of the functions to the array, when evaluating the functions only the last value of the parameter is being used.

Perhaps a simple example explains this best

a = Array[0, 2];
For[i = 1, i <= 2, ++i,
 a[[i]] = Function[{x}, i + x];
]

Giving the result

a={Function[{x}, i + x], Function[{x}, i + x]}

Now if I use $x=0$ (via the Through[] function), I would expect to have the result $\{1,2\}$ because $i=1$ for the first element and $i=2$ for the second element. However, the actual result I get is $\{3,3\}$. This occurs because when I evaluate the statement the current value of $i$, being $i=3$ causing the For[] loop to break, is used.

Question: How do I get the functions to use the value of $i$ they were created with, instead of the current value.

I know there is something similar to this in JavaScript, but can't remember the correct term for it.

$\endgroup$

marked as duplicate by Mr.Wizard Jan 29 '17 at 19:42

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

6
$\begingroup$

Short answer is that this will work as you expect:

 a = Array[0, 2];
    For[i = 1, i <= 2, ++i,
      With[{i = i}, a[[i]] = Function[{x}, i + x]];]

The reason why things didn't work out as you expect is that Mathematica is very different from other languages. Functions do not - as you might know from other languages - do some automatic conservation of scope at the time they are generated (you probably were looking for the term "closure"). That mechanism can in Mathematica be achieved by different means but is not automatic.

In Mathematica what you have to understand is the evaluation order, and I think the explanation in the documentation is a good starting point, when you know the terms "evaluation order" and "nonstandard evaluation" you will also find a lot of useful questions and answers on this site.

One more note is that you should not get into the habit of using For in Mathematica, it is never a good solution, see e.g. this question and answers for more details. Here is how I would solve your problem:

a = Table[With[{i = i}, Function[i + #]], {i, 2}]
Through[a[0]]

or even, but that is admittedly a bit tricky:

a = Function[i, # + i &] /@ Range[2]
$\endgroup$

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