lua-users home
lua-l archive

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




On Thursday, January 2, 2014, Sir Pogsalot wrote:



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 --

I haven't run into this issue. Ever. 

That's not to say that I couldn't change things around and us a design that would benifit from such a feature.  In fact, I believe Penlught does this for me, so in a sense, the problem is solved for me and I don't see it because it got done taken care of. 

Anyway, I generally make many more objects than I do classes. If Lua recursively checked the metatable's metatable, you'd be encouraging code that would speeds the creation of nested classes at the significant expense of actually using them. 

Isn't that what Ruby is for?

-Andrew