Where I can get activation from the metamethods while using function in table like this: tbl.myIndex(myParameters)?

37 views Asked by At

I hope you all can help me. So, I want to know when I call function in table like this which metamethod is activating:

local myTbl = setmetatable({
     myIndex = function(myParam)
         print(myParam)
     end
}, {
    -- Which is the metamethod that activates itself while using myIndex
})

I tried EVERYTHING!!! I mean. I made metatable and I used every single metamethod and nothing is called from the metamethods I used.

1

There are 1 answers

4
Alexander Mashin On

If you remove myIndex from the table, myTbl.myIndex () will activate the __index metamethod, which can either be a function (table, key) or a table.

myIndex () will only be called if __index (table, key) takes care of that, or if there is __index.myIndex function doing what you want.

See 13.4.1 – The __index Metamethod from Programming in Lua.

Update, after reading comments: By manipulating metatables and redefining functions you can effectively add new metamethods (e.g., by redefining the globals pairs() and ipairs() you can enable in Lua 5.1 __pairs and __ipairs metamethods, introduced in Lua 5.2).

The metatable is usually set in a 'wrapper' function that receives a table and returns its extended / enriched version. Like this:

local new_metamethod_name = '__method'

local function set_extended_metatable (t, mt)
    local old__index = mt.__index -- remember to emulate later, if any.
    mt.__index = function (table, index)
        if type (mt [new_metamethod_name]) == 'function' and type (t [index]) == 'function' then
            -- invoke the new metamethod for methods only, not properties:
            mt [new_metamethod_name] (table, index)
        end
        return t [index] -- return data from the original table, if any.
            -- emulate mt.__index, if any:
            or type (old__index) == 'function' and old__index (table, index)
            or type (old__index) == 'table' and old__index [index]
    end
    return setmetatable ({}, mt) -- for {}, __index will be always called.
end

local dumb_table = {
    myIndex = function (myParam)
        return ('In myIndex(). myParam is ' .. tostring (myParam))
    end,
    someProperty = 43
}

local smart_table = set_extended_metatable (dumb_table, { __method = function (tbl, key)
    print ('Invoking the new metamethod')
end })

print (smart_table.myIndex (42)) -- __method() called.
print (smart_table.someProperty) -- __method() not called.