Confused with setmetatable

local myTable = {}

local tab = {}

tab.__index = function()
	print("fired")
end

setmetatable(myTable, tab)

print(myTable[1])

I’ve a code that connects tab which is a metatable to myTable. I’m confused with how tab.__index fires if I try to index a nil value in myTable ?

You have the arguments of setmetatable backwards. The first argument is the table you want to assign a metatable to, the second argument is the table that will be the metatable of the first argument.

1 Like

I want tab to be the metatable for myTable.

I’m doing something wrong in this line.

myTable.__index = function()
	print("fired")
end

Why though? tab doesn’t contain any metamethods, so add the metamethods to tab instead of myTable

1 Like

I don’t get by what you mean.

Doing __index on tab works.

local myTable = {}

local tab = {}

tab.__index = function()
	print("fired")
end

setmetatable(myTable, tab)

print(myTable[1])

There you go, your problem solved.

Yes the problem does solve but I would like to know how does it work when you do it on tab?

If you do setmetatable(tab, tab) then tab is its own metatable and indexing for a nil value would cause a C stack overflow.

1 Like

Does it work because

setmetatable(myTable, tab)

tab is myTable’s metatable and contains the metamethods? But whenever you index a nil value in myTable, how does tab fire then? That’s the confusion I have.

incap you’re doing a bad job of explaining this smh.

The metatable and base table aren’t the same table. When you do setmetatable, you’re telling the Lua interpreter that myTable should follow tab’s rules.

__index works when you do t.k, index’s function parses the table itself and the key you’re attemping to index.
You can also set __index to another table

If you want to bypass it, you use rawget()

The only confusion I have is that how does tab.__index fire if I try to index a nil value in myTable ?

Because myTable’s metatable was tab. And tab contained that metamethod.

2 Likes

I dont understand fully what you mean but the index would just return nil

if foo.bar is nil then it would return nil
print(foo.bar) → nil

If you mean in the context of inheritence, (and you have the __index set to another table), it looks in that table aswell for a value. It will still return nil if it cant find it there either

local tab1 = {a = 1}
local tab2 = setmetatable({}, {__index = tab1})

print(tab2.a) --> 1 Even though tab2 doesn't have an a key, it can find it because it exists in the __index pointer
1 Like

Oh, I see. I’m pretty certain we can’t use metamethods on tables right or can we?

metatables are regular tables. They dont hold any special significance until you put them through setmetatable’s second arg.

I know that but I want to know can we use metamethods on normal tables?

Yes.

__index = table2
__newindex = table2

It merely just points Lua to another table when either making a new index, or indexing an existing one. As far as I know, these are the only two that will accept a table value.

Alright. I have one last question, I was told that using metamethods on tables caused the table to act as a metatable. Correct?

If your table is parsed as the second arg in setmetatable then yes.

setmetatable’s syntax is

table setmetatable(table Table, table Metatable)
1 Like

Thanks helping me grasp the concept.