Learning Lua can be a little tricky. The idea of variables implicitly being global can be confusing for some people, so using new users often dropped the much-needed local keyword. If you are concerned about accidentally creating globals there is a quick and easy check you can do you show you when/where you are creating them!
To implement this we are going to create a new metatable for the globals table. If you didn’t already know, all globals in Lua are stored in a table called the “environment“. It is accessible anywhere in Lua by accessing a table called “_G“. The fact that all globals are stored in the same table allows us to take advantage of a nifty metamethod call __newindex.
- Use “rawset(myTable,key,value)” to skip this metamethod.
- (If the __newindex function does not set the key on the table (using rawset) then the key/value pair is not added to myTable.)
This is exactly what we’re looking for!
1 2 3 4 5 6 7 8 9 10 11 |
setmetatable(_G, {__newindex = function(self, key, value) if not Engine:AllowGlobals() then Engine:StopWithError("Invalid Global created") else -- Set value normally rawset(self, key, value) end end }) |
With this setup, you can see what this example will do:
1 2 3 4 5 6 7 |
-- OK local testVar1 = 5 -- Not OK, invalid global testVar2 = 17 |
You can handle the invalid global creation however you want. In my case I called a function that would halt the game and present the user with an error where it occurred:
Another nice trick you can do is make a global function that will explicitly create a global. This clearly outlines when you are creating a new global and can make your code a bit easier to follow. A example of such a function looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
DeclareGlobal = function(name, value) -- Allow creation of our new global Engine:SetGlobalCreation(true) _G[name] = value -- Turn off global creation Engine:SetGlobalCreation(false) end --[[ Example usage ]] -- Not OK testGlobal = 5 -- OK DeclareGlobal("testGlobal", 5) |
You can expand this idea to work with any table you’d like as well. While I won’t go into in this post, you could easily set up a system in which you must explicitly declare key/values in tables to help prevent erroneous variable creation.
Hopefully this can help a few people from bashing their head on their keyboard because of a few typos!