Tobias Gierke
Tobias Gierke

Reputation: 482

Closure over numeric for-loop variable in Lua

I have a question about Lua, closures and local variables.

From my understanding, the loop variable in a numerical for-loop is implicitly local so I was expecting the following code to behave identical.

local a = 1
t1 = function()
  return a
end
a = 2
t2 = function()
  return a
end
print( t1() )
print( t2() )

table = {}
for i=1,2 do 
  table[i] = function() 
    return i
  end
end
print( table[1]() )
print( table[2]() )

To my surprise, it did not. Why does the code print

2
2
1
2

and not

2
2
2
2

?

Upvotes: 1

Views: 34

Answers (2)

shingo
shingo

Reputation: 27341

Early Lua manual has an equivalent code for the for statement:

for v = e1, e2, e3 do block end

-- is equivalent to the code: 

do
  local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
  if not (var and limit and step) then error() end
  while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
    local v = var
    block
    var = var + step
  end
end

It can be seen that the loop variable v is declared at the beginning of each iteration, in other words, the loop variable for each iteration is independent.

Upvotes: 1

Ivo
Ivo

Reputation: 23277

Each i is local to their iteration but so is each of the function declarations. They refer to their corresponding i. Even if the function didn't return i but a constant, like for example

table = {}
for i=1,2 do 
  table[i] = function() 
    return 5
  end
end
print( table[1] )
print( table[2] )
print( table[1] == table[2] ) -- false

you will see that the prints will be different. (I removed the () part in the print so you can see the memory address to the functions)

Upvotes: 0

Related Questions