As a new — or relatively new — Lua/Solar2D programmer, are you confused by console errors like this?
Runtime error /Users/yourname/Projects/AwesomeGame\menu.lua:4: attempt to index global 'button' (a nil value) stack traceback: [C]: in function 'error' ?: in function 'gotoScene' /Users/yourname/Projects/AwesomeGame\main.lua:16: in main chunk
If so, then you need to learn a very important programming concept known as scope. Scope impacts Lua's ability to "see" variables
When you think of terms like "telescope" or "microscope," you think of devices that help you see, and see things within a limit — for instance, very small things in a microscope. In programming terms, scope is used to define what parts of your code can "see" variables, objects, and functions that you have created. In Lua, there are two main scope controls: global and local.
Global variables/functions can be seen anywhere in your program. "Great, I'll use global scope for everything!" you might say, but global objects can actually be quite bad! In fact, new programmers should avoid using global variables.
One reason why globals are dangerous is that — because they have no visibility limits — they can be expensive to use in regards to performance. In fact, if a global variable is accessed in a
Global variables/functions also have the inherent risk of being accidentally
_W in one Lua file and assign it a value of
320, you may accidentally create another global variable
_W in another file, assign it a different value, and effectively "trash" the first declaration. This could obviously have unexpected consequences in the first file which expects
_W to have a value of
The global scope is discussed in more detail in the Goodbye Globals! tutorial, along with a convenient method to create/access
In Lua, the preferred scope is local which you control by using the
local declaration before you define a variable/function. For example:
local function someFunction() end
When you prefix a variable or function with
local when you first create it, it becomes available to that block of code and any "children" blocks contained within. This concept is highlighted by the following two examples:
local function addTwoNumbers( number1, number2 ) -- Create variable "sum" local only to this "addTwoNumbers()" function local sum = number1 + number2 print( sum ) -- This works! end print( sum ) -- This does NOT work (prints "nil" meaning it's unknown to Lua)
In this case, the function
addTwoNumbers() defines a new block of code. Inside this block, we create a new variable named
sum. This variable has the
local keyword, meaning it's only visible to the function
addTwoNumbers() — no other code in this module or overall project will be able to "see" the
sum variable. Thus, when the function ends, there is no longer a variable known as
nil will be printed to the console.
local function addTwoNumbers( number1, number2 ) local sum = number1 + number2 if sum < 10 then print( sum .. " is less than 10" ) local secondSum = sum + 10 end print( secondSum ) -- This does NOT work (prints "nil" meaning it's unknown to Lua) end
Like the first example,
sum is local to
addTwoNumbers(). That lets us add two numbers, and it's also visible inside the block started by
if sum < 10 then
secondSum) is created, and that variable becomes local only to the
secondSum outside of the
secondSum doesn't exist at that point in execution.
Consider a block of code like this:
local i = 999 for i = 1, 10 do print( i ) -- prints 1, 2, 3, .. 10 end print( i ) -- prints 999
Here, a local variable
i is set to
999 on line 1. In addition, a loop index variable of
i (line 3) is used, but this
i is local only to the
for loop. As the loop executes, its value represents the values
print( i )
i will forget its final value from the loop and return to its previous definition (usually
nil). Following that, the local variable
i which was declared before the
for loop is printed to the console (
print( i ) on line 7
999. This is because for loops — just like functions — are blocks and they adhere to the same scope rules associated with blocks.
Hopefully, this tutorial has illustrated that scope, as an overall concept, is relatively straightforward. When you use the keyword
local, the variable can only be accessed at that block level or within any child blocks. With that in mind, if your variables or functions need to be seen at a wider level, simply move them above/outside the block or define them near the top of the module.