1

I need userdata objects to support both methods and the index operator (with integer indices). Is there a way to achieve this in a common metatable without simulating methods via a function?

I tried chaining metatables, by setting metatable(object).__index to a table with the actual methods, and metatable(metatable(object).__index).__index to a function that implements the index operator. However, that function is called with the first __index table as an argument, instead of the original object. Tbh this seems like a design oversight, since it makes much more sense to pass the original object when the __index metamethod is a function. Regardless, is there a way to achieve what I want without explicitly checking for method names in the __index function?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
riv
  • 6,846
  • 2
  • 34
  • 63

2 Answers2

2

You could use a single __index function that both refers to the method table and handles integer keys.

function metatable:__index(key)
  if type(key) == 'string' then
    return methodTable[key]
  elseif type(key) == 'number' then
    return key * 42 + #self
  end
end
luther
  • 5,195
  • 1
  • 14
  • 24
1

When you set __index to a table, Lua automatically does a normal table lookup for the key in the __index table. It's completely equivalent to debug.getmetatable(obj).__index[k], and will do a recursive __index lookup or function call if the __index table has its own __index table.

Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85