lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]





On Fri, Dec 27, 2013 at 12:46 PM, Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> wrote:
> I don't understand why this isn't working: http://pastebin.com/kGX5Eay0
> When asking for #t, it should check the metatable "meta" for a __len
> method. But this doesn't seem to invoke "meta"'s __index metamethod.

The manual says that access to metatables are raw:

        metatable(obj)[event]
        should be read as
        rawget(getmetatable(obj) or {}, event)

http://www.lua.org/manual/5.2/manual.html#2.4


I very much so disagree with this, because of how tedious it makes proxy tables to implement.  Currently the metatable for a 'proxy table' would be something like this:

real_table = setmetatable({}, { --[[ imagine many metamethods defined here on the real table ]] })

proxy_table = setmetatable(
  {},
  {
    __index = function (_, k) return real_table[k] end,
    __newindex = function (_, k, v) real_table[k] = v end,
    __len = function () return #real_table end,
    __mul = function (rhs, lhs) --[[ this one is tricky, gotta figure out which is self ]],
    etc...
  })

If accesses to metatables were not done rawly, you could just define the proxy object as:

proxy_table = setmetatable({}, setmetatable({}, { __index = real_table }))

Then you might ask, "well, what's the point of a proxy that just passes everything through?"

Recently I've been trying to make it so a table that has a metatable already can be used with yet another metatable -- similar to what I'm sure OP was saying about inheritance.  I wanted to have something like:

local tmp = emulate(some_table_with_established_mt, table)

tmp:insert('whatever')

This way I can either use some_table_with_established_mt or tmp to refer to the same table while benefiting from the friendliness of either's metatable *and* still being able to use it like a regular table.  (maybe this is too ambitious...)

I would do that (if it were possible) with this:

local emulate =
    function (t, extra_mt)
        return setmetatable({}, setmetatable({ __index = extra_mt }, { __index = real_table }))
    end

((i think))

Anyway, much simpler than torturously defining all the metamethods to "chain through".

-- toodles --