lua-users home
lua-l archive

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


Dear Lua community,

I'm experiencing problems with __index metamethod when it is a function or a table. I'm working with a class extension for Lua with hieritance.
When dealing with nested __index tables (for class hieritance), I realize that keys of inner nested __index table receive as argument (self) the caller table, however, if the nested __index is a function, it doesn't receive the caller table, but the table where metatable is being defined.

In order to make it clearer, I have written two minimal examples where this behavior is present:

Nested __index tables example:

local metainstance = {
  __index = {
    foo = function(self) return self.v end,
  },
}
setmetatable(metainstance.__index, {
      __index = {
bar = function(self) return self.v end,
      },
})
setmetatable(getmetatable(metainstance.__index).__index, {
      __index = {
baz = function(self) return self.v end,
      },
})
local class = {
  new = function(v) local t = {v=v} setmetatable(t, metainstance) return t end,
}
local o = class.new(5)
print( o:foo() )
print( o:bar() )
print( o:baz() )

Executing this example in lua produces as output the expected:
5
5
5



Mixed __index table and __index functions:

local metainstance = {
  __index = {
    foo = function(self) return self.v end,
  },
}
setmetatable(metainstance.__index, {
      __index = {
bar = function(self) return self.v end,
      },
})
setmetatable(getmetatable(metainstance.__index).__index, {
      __index = function(self,key)
if key == "baz" then return rawget(self,v) end
      end,
})
local class = {
  new = function(v) local t = {v=v} setmetatable(t, metainstance) return t end,
}
local o = class.new(5)
print( o:foo() )
print( o:bar() )
print( o:baz() )

The output of this code is:

5
5
lua: min.lua:24: attempt to call method 'baz' (a nil value)
stack traceback:
min.lua:24: in main chunk
[C]: in ?

because the nested __index function receives as argument a table which is not the caller o table, and the rawget(self,v) function returns nil

I don't have the intuition why this two approaches are not exactly the same, and it will be nice and very grateful to get an explanation of this behavior.
Thanks!

--
Pako ZM :)
http://cafre.dsic.upv.es:8080/~pako/