Reputation: 2277
I would have expected the integer 'i' in this Dart program to have been set to 9 before the first function was called. However the output for this program is...
0, 2, 4, 6, 8, 10, 12 ,14, 16, 18
When I would have normally expected 10, 11, 12, 13.... as it is with JavaScript, C# etc..
Dart Lang Output: 0, 2, 4, 6, 8, 10, 12 ,14, 16, 18
typedef int TestFun(int x);
void main()
{
List<TestFun> functionList = new List<TestFun>();
for ( int i = 0; i < 10; i++) {
functionList.add( (int x) => x + i );
}
for ( int j = 0; j < 10; j++)
{
print(functionList[j](j));
}
}
Equivalent JavaScript.... Output 10,11,12...
var functionList = new Array;
for ( var i = 0; i < 10; i++) {
functionList[i] = function (x) { return x + i } ;
}
for ( var j = 0; j < 10; j++) {
alert( functionList[j](j) );
}
Equivalent C#.... Output 10,11,12...
public delegate int TestDel(int x);
public static void Main(string[] args)
{
IList<TestDel> functionList = new List<TestDel>();
for ( int i = 0; i < 10; i++)
{
functionList.Add((int x) => x + i);
}
for ( int j = 0; j < 10; j++)
{
System.Console.WriteLine(functionList[j](j));
}
}
Is this a Dart bug? Can someone explain this behavior to me?
Upvotes: 2
Views: 317
Reputation: 71783
Dart deliberately avoids the error-prone behavior of JavaScript here.
A for loop that declares its own variable will have a new version of that variable for each iteration. This goes both for for(var x = ...;;)
and for (var x in ...)
(and in the latter case, the variable can even be final).
Example showing that each iteration introduces a new independent variable:
class Box {
final Function set;
final Function get;
Box(this.get, this.set);
String toString() => "[${get()}]";
}
main() {
var boxes = [];
for (int i = 0; i < 5; i++) {
boxes.add(new Box(()=>i, (x) { i = x; }));
}
print(boxes); // [[0], [1], [2], [3], [4]]
for (int i = 0; i < 5; i++) {
boxes[i].set(i * 2 + 1);
}
print(boxes); // [[1], [3], [5], [7], [9]]
}
Upvotes: 7
Reputation: 657781
Your conclusion seems weird to me.
The first closure you add is actually (i = 0)
functionList[i] = function (x) { return x + 0 } ;
In the second for
loop (first iteration) you execute this first function with the argument 0
. How should this result to 10
?
EDIT
To avoid the behavior mentioned by lrn you can put the variable inside an object
typedef int TestFun(int x);
class Int {
int val;
Int(this.val);
}
void main() {
List<TestFun> functionList = [];
for (Int i = new Int(0); i.val < 10; i.val++) {
functionList.add((int x) => x + i.val);
}
for (int j = 0; j < 10; j++) {
print(functionList[j](j));
}
}
Upvotes: 0