daven11
daven11

Reputation: 3035

nesting metatables in lua

In the code below it's my attempt to nest metatables on __index, but it's not working. What I want to do is if the value is t1 or t2 then return the associated value, otherwise call the function on the innermost __index. Is this possible?

so in the below x["hello"] can I return a value. I know I can just use a function on the outermost __index, but it seems I should be able to do this somehow using nested metatables.

tia.

x = { val = 3 }      -- our object

mt = {
    __index = {
        t1 = 2,
        t2 = 3,
        __index = function (table, key)
            print("here"..key)
            return table.val
        end
    }
    }

setmetatable(x, mt)
print(x["t1"]) -- prints 2
print(x.t2) -- prints 3
print(x["hello"]) -- prints nil???

This works but it seems like I could do it with metatables

x = { val = 3 }      -- our object

mt1 = {
        t1 = 2,
        t2 = 3
    }

mt = {
        __index = function (table, key)
            local a = mt1[key]
            if a == nil then
                print("here"..key)
                a = "test"
            end
            return a
        end
}

setmetatable(x, mt)
print(x["t1"])
print(x.t2)
print(x["hello"])

Upvotes: 1

Views: 2468

Answers (2)

daven11
daven11

Reputation: 3035

..and for anyone following along at home, here it is with nested metatables inline. Thanks for the tip Alexander that makes it a lot cleaner.

x = setmetatable(
    { val = 3 },
    {
        __index = setmetatable({
                t1 = 2,
                t2 = 3
            },
            {
            __index = function (table, key)
                print("here"..key)
                return key
            end
            }
        )
    }
)
print(x["t1"])
print(x.t2)
print(x["hello"])

Upvotes: 2

daven11
daven11

Reputation: 3035

This works, but can I do it without declaring mt2?

x = { val = 3 }      -- our object

mt2 = {
        __index = function (table, key)
                print("here"..key)
            return key
        end
}

mt = {
        __index = {
        t1 = 2,
        t2 = 3
        }
}

setmetatable(mt.__index, mt2)
setmetatable(x, mt)
print(x["t1"])
print(x.t2)
print(x["hello"])

Upvotes: 0

Related Questions