Hello! I’ve been utilizing metatables for a lot of my projects for a while now and in the process I have been trying to study as many aspects of this feature as I can to fully apply their potential.
Recently I’ve come across ‘__mode’ in the midst of my studying and was wondering if my takeaway was valid. So here it is:
--[[ SETTING MODE TO 'v' ]]]
local WeakValues = setmetatable({}, {__mode = 'v'})
local Table = {}
table.insert(WeakValues, Table)
-- Will this make the table stored inside WeakValues get garbage collected?
Table = nil
If this isn’t the case, can someone explain why this is and what setting weak values really means? Thank you!
The __mode field in a metatable allows you to create weak tables, enabling references to objects that do not prevent those objects from being garbage collected.
A weak table is a table that holds “weak” references to its keys, values, or both. When an object referenced by a weak key or value is no longer referenced elsewhere, it becomes eligible for garbage collection.
Setting the __mode Field
The __mode field in a metatable is a string that specifies the weakness of the keys and values in the table. It can contain the following characters:
"k": The keys are weak references.
"v": The values are weak references.
You can combine these characters to specify both weak keys and weak values by setting __mode to "kv".
... setmetatable({}, {__mode = "k"}) -- allow for weak keys
... setmetatable({}, {__mode = "v"}) -- allow for weak values
... setmetatable({}, {__mode = "kv"}) -- allow for weak keys and weak values
Example:
local t = {}
setmetatable(t, {__mode = 'k'})
do
-- closure
local key = {} -- key is the reference to this table (object)
t[key] = 123
end
collectgarbage() -- force a garbage collection cycle
-- variable 'key' is out of scope since it was created in a closure
-- after garbage collection, the object held by key is removed from 't'
for k, v in pairs(t) do
print(k, v)
end
-- prints nothing
local key
do
key = {}
t[key] = 123
end
collectgarbage()
-- key is still valid since it's a global variable
for k, v in pairs(t) do
print(k, v)
end
-- prints table: 0x56144f2e36e0 123