Sadie Kaye
Sadie Kaye

Reputation: 27

how to extend lua metatables with (something like) __index

The following session shows what I was trying to. I must have misread some documentation somewhere that (I thought) said that an __index item in a metatable provides a default when the table doesn't provide an item for that key. The point is it doesn't work on metatables themselves but I have no idea why not. Where in the documentation is this explained, and what can I do about it in such cases?

Thanks!

> a = {}
> b = {}
> setmetatable(a,b)
table: 0000000002631ae0
> c = { __tostring = function(x) return "X" end }
> setmetatable(b,{ __index=c })
table: 0000000002631560
>
> print(a)
table: 0000000002631ae0
> -- I was expecting: X
> print(getmetatable(a).__tostring)
function: 0000000002633840
> print(tostring(a))
table: 0000000002631ae0
> -- Again, expecting X
> print(getmetatable(a).__tostring(a))
X
>

Here is another example.

> a = {}
> b = {}
> setmetatable(a,b)
table: 0000000002631fe0
> c = { __add = function(x,y) return "X" end }
> setmetatable(b,{ __index=c })
table: 00000000026316a0
>
> print(a+a)
stdin:1: attempt to perform arithmetic on a table value (global 'a')
stack traceback:
        stdin:1: in main chunk
        [C]: in ?
>

So this problem is not specific to print and tostring. Of course in real situations I want to have a lot of different objects sharing a lot of metatable values without having to copy everything every time...

Upvotes: 2

Views: 786

Answers (1)

Spar
Spar

Reputation: 1762

This is because __index is related to indexing operations like tbl.var. Lua doesn't use __index to get other metamethod (like __tostring).

You are using print which invokes __tostring directly from the metatable, it doesn't use __index here.

__index: The indexing access operation table[key]

Learn more: https://www.lua.org/manual/5.4/manual.html#2.4

The solution would merging metatable c with b.

setmetatable(b,{ __tostring = c.__tostring })
print(b) -- X

Upvotes: 1

Related Questions