I can't say I've ever heard of strong tables before so I can't provide much insight for that. Weak tables however I understand a bit better.
The first thing I'll say is that weak tables have limited uses. If you find yourself trying to use them when there's a another solution you're probably just making life more difficult for yourself. That being said, when using them correctly they're extremely useful.
I think the most important line from the wiki in regards to weak tables is the following:
"If a reference to an object is only held inside weak tables, Lua will collect the object eventually."
What this means is that depending on our mode if the keys or values or one of the two (both) aren't referenced anywhere else in the active code their entry will be removed from the table.
Let's look at some examples:
Note: the garbage may not collect in the 1 second interval so if having difficulties either run again or change the wait time.
local t = setmetatable({}, {__mode = "k"});
local k = game.Workspace.Part;
t[k] = "Value";
for k, v in next, t do print(k, v); end
wait(1);
k = nil;
for k, v in next, t do print(k, v); end
wait(1);
for k, v in next, t do print(k, v); end
print("Done.")
Now looking at values:
local t = setmetatable({}, {__mode = "v"});
local v = game.Workspace.Part;
t["Key"] = v;
for k, v in next, t do print(k, v); end
wait(1);
v = nil;
for k, v in next, t do print(k, v); end
wait(1);
for k, v in next, t do print(k, v); end
print("Done.")
Finally keys and values:
local t = setmetatable({}, {__mode = "kv"});
local k = game.Workspace.Part1;
local v = game.Workspace.Part2;
t[k] = v;
for k, v in next, t do print(k, v); end
wait(1);
v = nil;
for k, v in next, t do print(k, v); end
wait(1);
for k, v in next, t do print(k, v); end
print("Done.")
local t = setmetatable({}, {__mode = "kv"});
local k = game.Workspace.Part1;
local v = game.Workspace.Part2;
t[k] = v;
for k, v in next, t do print(k, v); end
wait(1);
k = nil;
for k, v in next, t do print(k, v); end
wait(1);
for k, v in next, t do print(k, v); end
print("Done.")
I think the main thing you need to be wary other than setting variables to nil explicitly is scope. If you create entries in a table using variables that are local in scope they will become nil when you leave that scope. Here's what I mean:
local t = setmetatable({}, {__mode = "k"});
do
local k = game.Workspace.Part;
t[k] = "Value";
end
for k, v in next, t do print(k, v); end
wait(3);
for k, v in next, t do print(k, v); end
So when is this useful? I personally have found this most useful for OOP (object oriented programming). We can use weak-tables to store private-values that we don't want the user to mess with in the class.
Here's an example:
local class = {};
local class_mt = {__index = class};
local class_ref = setmetatable({}, {__mode = "k"});
function class.new(x, y)
local self = {};
self.x = x;
self.y = y;
self = setmetatable(self, class_mt);
class_ref[self] = {};
class_ref[self].magnitude = math.sqrt(x*x + y*y);
return self;
end
function class:getMagnitude()
return class_ref[self].magnitude;
end
local a = class.new(1, 2, 3);
local b = class.new(-3, 7, 32/4*(-8));
print(a.x, b.y);
print(a:getMagnitude());
for k, v in next, class_ref do print(k, v); end
b = nil;
wait(1);
for k, v in next, class_ref do print(k, v); end
Of course these "private" values could be accessed as long as the programmer has access to the class_ref table, but if you're writing your class in a module then it's as simple as not returning said table. I use this exact technique to store cframe components in my lua cframe class.
Hope this helped clear some stuff up.
1 comment
Nobody really says "strong table", a table merely has weak keys and/or values or doesn't.