Corona SDK Pro Tip of the Day #10
Global variables

Use a special Lua script to detect global variables.

One of the oversights of Lua language is the local keyword. Not the keyword itself, but the fact that by default all variables are created global. It should have been the other way around.

It is easier for beginners, but introduces a certain discomfort for Pro developers.

If you forget to write local in front of your variable, you can run into memory leaks or weird behaviour of your app.

However, thanks to the flexibility of Lua, we can hook up a special listeners for when a new global variable is introduced and raise a runtime error saying that it's not supposed to happen.

It's is important to perform such check only during the development, when your application is in production don't introduce artificial runtime errors. Moreover, some 3rd party plugins or libraries can contain such errors and it may be impossible to fix them on your own. So it makes sense to perform such check in the Simulator only.

Save this code as strict.lua and require it in your main.lua.

if system.getInfo('environment') == 'simulator' then  
    -- Prevent global missuse
    local mt = getmetatable(_G)
    if mt == nil then
      mt = {}
      setmetatable(_G, mt)

    mt.__declared = {}

    mt.__newindex = function (t, n, v)
      if not mt.__declared[n] then
        local w = debug.getinfo(2, 'S').what
        if w ~= 'main' and w ~= 'C' then
          error('assign to undeclared variable \'' .. n .. '\'', 2)
        mt.__declared[n] = true
      rawset(t, n, v)

    mt.__index = function (t, n)
      if not mt.__declared[n] and debug.getinfo(2, 'S').what ~= 'C' then
        error('variable \'' .. n .. '\' is not declared', 2)
      return rawget(t, n)

Here we first check if we are running inside the Simulator. Then we obtain a metatable for the global scope table _G. All global variables end up in _G, _G is a global variable itself, so yes, it is possible to write _G._G._G._G._G._G._G._G._G._G._G.

__declared holds all already declared global variables and it is used to check if a given global variable is properly declared or not.

__newindex and __index are special meta functions that get called when a global variable is about to be set or read.

Usually you want your global variables to be set in the top scope of your Lua files.


-- It's OK to declare a global var here
aGlobalVar = 'I am Global'

local function someFunctions()  
    -- It's not OK to declare a global variable inside any function
    desperateVar = 'I want to be global'

When they are in the top scope, they are easily seen and controlled. But most often you make mistakes inside functions. Here strict check works and helps to detect such situations.

Indie Game Developer