سؤال

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?

هل كانت مفيدة؟

المحلول

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]]
}

نصائح أخرى

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));
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top