Reputation: 65
I'm trying to learn metatables in Lua and I came across the following example: -
local my_metatable = {}
local my_tab = {}
setmetatable(my_tab, my_metatable)
-- Set the __index metamethod:
my_metatable.__index = function (tab, key)
print("Hello, " .. key)
return "cruel world"
end
-- Trigger the __index metamethod:
print("Goodbye, " .. my_tab["world"])
The result is:-
Hello, world
Goodbye, cruel world
My question is - what does the variable tab
do, in my_metatable.__index = function (tab, key)
. I can change it to anything and it doesn't affect the program in any way.
Thanks!
;^) Zalokin
Upvotes: 0
Views: 1630
Reputation: 58
My question is - what does the variable
tab
do, inmy_metatable.__index = function (tab, key)
the tab arg is the table it self if you print the table outside the metamethod and then print the tab arg inside the metamethod you will that they have the same table address (think of it as self in python or this in c++)
I can change it to anything and it doesn't affect the program in any way.
this is wrong we can change the arg and it will affect the table (check the code above ):
local my_metatable = {}
local my_tab = {}
setmetatable(my_tab, my_metatable)
my_metatable.__index = function(tab, key)
print("Hello, " .. key)
print(tab)
setmetatable(tab, {})
end
print("1", my_tab)
print("2", my_tab.blan)
print("3", my_tab.blan)
Explanation:
print("1", my_tab)
This prints the the memory address (reference) of my_tab
.
print("2", my_tab.blan)
Accessing my_tab.blan
triggers the __index
metamethod :
my_tab
.my_tab
to an empty table {}
.Since the __index
metamethod changes the metatable of my_tab
to {}
, the original metatable with the __index
metamethod is now gone. The __index
function does not return any value, so the printed value is nil
.
print("3", my_tab.blan)
Now, my_tab
no longer has a metatable with an __index
metamethod because it was overwritten by an empty table {}
in the previous step. Accessing my_tab.blan
again returns nil
since blan
is not defined in my_tab
and there's no __index
metamethod to handle it.
Here is the summarized output of the code:
1 table: 0x<address> -- address of `my_tab`
Hello, blan -- from the `__index` metamethod
table: 0x<address> -- address of `my_tab` (printed from within the `__index` metamethod)
2 nil -- `my_tab.blan` after `__index` is removed
3 nil -- `my_tab.blan` again
Upvotes: 0
Reputation: 2100
The tab
parameter is passed an argument of the table itself.
For example, given your code my_tab["world"]
, the parameters tab
and key
will be passed the arguments my_tab
and "world"
respectively. Because you didn't use the table in your __index
function, it didn't affect anything.
Here is a basic example of what it might be used for. Let us consider a special Array table that acts like an array but has some additional information:
Array = {
length = 0,
array = {}
}
mt = {
__index = function(tab, index)
return tab.array[index]
end
}
setmetatable(t, mt)
--now when Array[3] is written, what will actually be returned is Array.array[3]
print(Array[3]) --will actually print Array.array[3]
This isn't actually the best way to implement this functionality, but hopefully this gives you an idea of why the tab
parameter exists and what __index
can be used for as a result.
Upvotes: 0