Reputation: 303510
I believe the answer to this is "no", but I need to ask anyhow:
I have several nested tables of values, mostly with the same ~"schema" (hierarchy of names). For example, theme.person.child
has a value in each of these nested tables, e.g. a string like "#ffcc33"
.
Sometimes I would like to be able to reference theme.person
(which is usually a table) and "get" a string value instead of a name. I want a default value for all person
, regardless of the sub-key.
Is there any metamethod/key that would let me call the same function on table.person.child
and table.person
and always get a string? In code:
local theme1 = { person = { child='#ffcc33', adult='#00ffff', _default='#ff0000' } }
local theme2 = { person = '#ff0000' }
for _,theme in ipairs{ theme1, theme2 } do
print(somefunction(theme))
end
Is there any way to make both print statements output give #ff0000'
? Some magic other than :
function somefunction(x) return type(x)=='table' and x._default or x end
Upvotes: 1
Views: 367
Reputation: 29234
This is a little odd how you have this organized, but is this what you want? 'person' has to be a hard-coded property, or do you want to search all properties for _default
if they are a table?
local theme1 = { person = { child='#ffcc33', adult='#00ffff', _default='#ff0000' } }
local theme2 = { person = '#ff0000' }
function somefunction(tbl, param)
if type(tbl) == 'string' then return tbl end
return tbl._default
end
for _,theme in ipairs{theme1, theme2} do
print (somefunction(theme.person))
end
You could possibly use metatables if there's a standard you want to use, but then you have to set them on each table. __tostring
on a metatable would let you return whatever string you want when the table is converted to a string. In the code below I set the metatable on the person in theme1
so that it returns the _default
when doing a tostring()
on the table. __index
lets you return whatever values you want when a table is indexed. Here it works like a color
property that returns person._default
if person is a table or person otherwise.
local personmt = {
__tostring = function(t)
if type(t) == 'table' and t._default ~= nil then return t._default end
return tostring(t)
end
}
local thememt = {
__index = function(t, k)
if k == 'color' then
if type(t.person) == 'table' then return t.person._default end
return t.person
end
end
}
local theme1 = { person = { child='#ffcc33', adult='#00ffff', _default='#ff0000' } }
local theme2 = { person = '#ff0000' }
setmetatable(theme1.person, personmt)
for _,theme in ipairs{ theme1, theme2 } do
setmetatable(theme, thememt)
print('theme.person (__tostring):', theme.person)
print('theme.color (__index) :', theme.color)
end
Upvotes: 1