Why is .__index used like this?

I understand the .__index metamethod written like so:

local myTable = {10, 15, 20}

local myMetaTable = {
	__index = function(table, index)
		print("No data at this index!")
		
		return 1
	end
}

setmetatable(myTable, myMetaTable)

local myNumber = myTable[4]
local addNumber = myNumber + 5

print(myNumber, addNumber)

But I am confused when its written like this:

local car = {}
car.__index = car

return car

What does this do? And is this different compared to my first coding example above, if so how?

1 Like

Is it fine if I use it the way I have display above instead of car.__index = car? Is there a difference?

When using a function as __index, you can manually retrieve the value. Specifying a table is a “secondary” thing to check, which is better used for referencing methods (which are usually unchanged).

1 Like

So, just clarifying, if I have:

local tycoon = {}
tycoon.__index = tycoon

function tycoon.new()

end

return tycoon

EDIT: What would this do?

I saw you last reply but I am still a little confused.

Well, you would set the metatable of it to itself, I guess? I haven’t ever defined the __index in the tycoon, I always do that in the constructor.

By itself, that does nothing other than create a property named __index on the table tycoon set to itself.

That usage however is useful when implementing inheritance/OOP and using the base table as the metatable. So building out that tycoon.new() method it becomes relevant

function tycoon.new(type: string)
  local self = {
    TypeOfTycoon = type
  }

  setmetatable(self, tycoon)

  return self
end

-- in other code...
local BurgerTycoon = tycoon.new("Burger")
local TacoTycoon = tycoon.new("Taco")

Now if you reference a property or method which does not exist on BurgerTycoon or TacoTycoon, the __index metamethod kicks in and it will failover to checking the base class, tycoon. Setting an __index metamethod to a table is simply a shortcut for a function that returns the corresponding key from the table, just like your function above.

You can learn more on the official Roblox style guide here: Roblox Lua Style guide, this is referred to as the “One True Pattern”.

2 Likes

Thanks so much for the reply.

One more question, what does this do?

local tycoon = {}
tycoon.__index = tycoon

function tycoon.new()
	local self = setmetatable({}, tycoon)
	
	return self
end

return tycoon 

setmetatable() both updates the first argument table in-place but also returns the now-modified table. So your example is equivalent to:

local self = {}
setmetatable(self, tycoon)
return self

That is, it creates a new empty table, sets the metatable of it, and assigns to the variable self, then returns self.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.