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