Default Values for Tables
Problem Definition Assume that it is necessary to have default values on a set of tables
- If the table does not have a value for a key then
- A default value is to be given. Note that in this case
- only one default per table is allowed
- If the table does not have a value for a key then
Problem Solution Discussion
1\. Each read of a value for a key from the table will return a value or if the key does not exist in the table a nil. 2\. A call to return an absent key can be intercepted by defining the __index metamethod. 3\. The __index metamethod can then return a default value 4\. The question becomes how to make the metatable efficient ``` _**Solution 1**_ ``` --[[This is a function which will set a default for a table. Note that a new metatable is created for each table. The function creates only one default per table. Each use of this function creates a closure this can be expensive in terms of memory used (metatable and default) if there are many tables]] function setDefault(table, default) local metatable = {__index = function () return default end} -- a new closure, when __index is called, default is known setmetatable(table, metatable) end theTable = {x=10, y=20} print(theTable.x, theTable.z) setDefault(theTable, -1) print (theTable.x, theTable.z) setDefault(theTable, 0) print (theTable.x, theTable.z) ``` _**Solution 2**_ ``` --[[Here we set default values for indices that are used that have no table entries by only using one metatable, saves memory. The function saves the default data in the table itself. It uses an oddly named variable, three underscores (___) as the variable name]] local metatable = {__index = function(t) return t.___ end} function setDefault(table, default) table.___ = default setmetatable(table, metatable) end theTable = {x=10, y=20} print(theTable.x, theTable.z) setDefault(theTable, -1) print (theTable.x, theTable.z) ``` _**Solution 3**_ ``` --[[set default values for indices that are used that have no table entries by only using one metatable, saves memory. The function here saves the default data in the table itself. In this case it uses the name "key" as the variable name Note: to create key it is set up as a table and created using a local variable. Its value is then initialize with the default (which can be of any type) within the setDefault function. This is somewhat obscure and subtle, we end up with an index and value pair where the index is an empty table (called key) and the value is the default]] local key = {} local metatable = {__index = function(t) return t[key] end} function setDefault(table, default) table[key] = default setmetatable(table, metatable) end theTable = {x=10, y=20} print(theTable.x, theTable.z) setDefault(theTable, -1) print (theTable.x, theTable.z) ```