Initializing Tables

If you're anything like me, then you also prefer to organize your code within one globalized table rather than multiple. Or even if you're not that way, and you prefer keeping all your code inside of localized tables within each file; everyone comes to the same hassle. Initializing the tables.

It always ticks me off having to waste a line to instantiate a new table. It always throws off the vibe of the file, it can also confuse the end-user when they're editing configuration files. So I have devised a small metatable based hack that fixes all of this.

Super = setmetatable({}, {
    __index = function(t, k)
        local temp = {}; rawset(t, k, temp)
        return temp
    end
})

If you know how metatables work in Lua, then this should make immediate sense to you. But if you don't. The __index metamethod is called whenever you try to retrieve an index within a table that doesn't exist. So in this case, let's say you wanted to initialize a configuration table to use in a configuration file. You would simply do: local CFG = Super.CFG and now the "CFG" variable references "Super.CFG". After this point, every time you reference "Super.CFG", it will be the same table, and you never had to explicitly instantiate it as a table.

I see it more as a failsafe than anything else. Because now, there will be no more scenarios where a table you reference doesn't exist. No more "attempt to index a nil value" errors (well, not at the top level).

Use Cases

In any case, one might ask why not use a statement such as:

local CFG = CFG or {}

The reason is that you have to assign this config variable to a global variable to have access to it, or just make it global outright. With the way I've written it, I don't even have to think about all the extra steps.

-- My way
local CFG = Super.CFG

-- Classic Way
Super.CFG = Super.CFG or {}
local CFG = Super.CFG

But it doesn't just have to be with tables. You can use the __index metamethod to set default values if they don't exist, rather than just receiving a nil return.

Accounts = setmetatable({}, {
    __index = function(t, k)
        local temp = 5--[[DEFAULT VALUE]]; rawset(t, k, temp)
        return temp
    end
})

However, doing it with values other than tables doesn't yield the same effect. Since tables are referenced values, you can edit them when you assign them to a variable. However, if you try the same with any other variable type, you will need to reassign the new value to the table, as demonstrated below.

local balance = Accounts.superzorik
balance = balance + 5

print(balance, Accounts.superzorik) -- 10   5

Accounts.superzorik = balance

print(balance, Accounts.superzorik) -- 10   10

Conclusion

Ultimately, whether you're a ten-year veteran or you're a novice just getting into programming. We all want to be able to write code as efficiently as possible. This is just one of the ways that I start my projects. Saving yourself a line here or there makes your files look much cleaner, and you always know there's a table ready whenever you need it.