Introduction
One odd thing about Lua when compared to other programming languages is, everything is global by default. Take this for example:
function func_a()
q_var = 7
end
func_a()
print(q_var)
Once func_a is called q_var is available and set to 7. Even outside of
func_a. You can mark a variable or function as local so it’s not global and
pretty much anything written in Lua that’s mildly complex will use local a
lot. Basically, global scope is default and anything that should be local
scope needs to be explicitly marked.
The For Loop
for loops are a special case in Lua when it comes to global scope.
Interestingly, the variables that are part of the loop declaration
are local to the loop itself. Without needing to be marked as such.
Let’s look at an example.
local c = { 1, 2, "a", "b" }
for _, v in ipairs(c) do
print(_, v)
end
print(_, v)
You’d expect the last print(_, v) to have the last values from the for loop
but they don’t! They’re both nil. Now, you might think Lua’s just clearing
the variables when the loop exits but that isn’t what’s happening.
A for loop is truly locally scoped when it comes to the variables that
are part of the declaration. The outer ones aren’t modified at all and
are simply “masked” in the loop itself. Here’s a demonstration.
local c = { 1, 2, "a", "b" }
local _ = "Underscore"
local v = "V"
print(_, v)
for _, v in ipairs(c) do
print(_, v)
end
print(_, v)
We’ve set both _ and v, and then we run the loop. Inspecting the output…
$ lua r.lua
Underscore V
1 1
2 2
3 a
4 b
Underscore V
Inside of the loop _ and v are the expected values coming from iparis.
However, once the loop exits both variables are back to their original values
from outside of the loop.
This isn’t exclusive to ipairs either. The same is true for pairs or even
counting (for v=1,10 do ... end). Basically, even though local isn’t used,
Lua is treating these variables as if they were declared within the loop as
local.
Conclusion
So, what does this all mean?
First, you can’t get the last value from the variables declaring a for loop.
Meaning, if you break early and you need the value you must set it to a
different variable. One not marked local within the loop, but you can use a
global in the loop and it will still be accessible once the loop exits. Though,
you probably should declare a local variable outside of the loop.
Second, you don’t have to declare the variables
as local outside of the loop. These variables are not created or internally treated
as a global so you don’t have to worry about them polluting the global
scope.
Third, if you have a variable and reuse it in a for loop declaration
it will be masked within the loop. The variable will be unaltered by
the loop and will have it’s original value once the loop ends.
Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.