#1468 js: Loop scope access from closures issue

dsav Thu 31 Mar 2011

Please, consider the following code:

Int[] ns := [,]
|->|[] fs := [,]    
for (Int i := 0; i < 10; ++i) {
  ns.add(20 + i)
}    
for (Int i := 0; i < 10; ++i) {
  Int n := ns[i]
  fs.add() |->| { echo(n) }
}
fs.each { it() }    

It prints 20..29 on Java (as intended). But on JavaScript it prints 29 ten times.

P.S. If each() is used instead of the second for, everything works fine.

vkuzkokov Thu 31 Mar 2011

It has to do with JS crazy variable scopes. This code

for (var i = 0; i < 10; ++i)
{
  var n = ns.get(i);
  fs[i] = function() { print(n) };
}

is close enough to what compiler generates. In JS n doesn't go out of visibility until we return from current function. each works because it calls a function on every iteration and thus creates a new scope each time.

Possible solution would be to generate something like

for (var i = 0; i < 10; ++i)
  function()
  {
    var n = ns.get(i);
    fs[i] = function() { print(n) };
  }();

Workaround is to stick to each and keep in mind JS variable scopes when using closures.

andy Thu 31 Mar 2011

Promoted to ticket #1468 and assigned to andy

Can be tricky - but I should be able to fix that in the compiler.

Login or Signup to reply.