Why should I use __mode?

Just give me an example of why I should use it. I’m trying to create my own class, and when I looked at a class (written by Egomoose) I saw that it uses this __mode. So I want to know what it is used for. I only know that it has something to do with weak values and weak keys, what and why I don’t know. I would also like to know when to use weak values or weak keys.

~~Eterna

1 Like

For your question on weak values and weak keys you can see this post.

1 Like

@JackEnforcement That solves a problem, but it doesn’t help me too much. Could you make an example (except from the link) where I can see more exactly how it is used?

There is an example of weak values in the post above.

__mode is used to set the “mode” for weak values/keys for metatables.

“v” = weak values
“k” = weak keys
“kv” or “vk” = weak keys and weak values

For example:

local weakvals = {__mode="v"}
local weak = setmetatable({},weakvals)
weak[1] = setmetatable({},weakvals)
weak[1][1] = workspace -- won't be collected, as its a global
wait(2)
print(weak[1])
3 Likes

Garbage collection stuff I suppose.

When __mode is "k", the keys of the table are weak.

When it is "v", the values are weak.

When it is "kv", the keys and values are weak.

An object (table, function, userdata, thread) is eligible for garbage collection when there are no more references to that object. Weak references don’t count, so if object has only weak references, it will be garbage collected

1 Like

Thank @incapaxx and @JackEnforcement a lot, but the last and most important question remains: Why should I use it?

In Roblox, you really don’t need to.

2 Likes

You will only need to use it if you’re writing a library and you’re operating on objects you don’t have full control over / knowledge of. If you’re writing your own game code you won’t need them.

For example, suppose that you’re writing a library and you want to attach additional information to objects that get passed to your library to “remember” information associated with the object. You can remember it like this:

function Library.foo(tb)
    local extraData = storage[tb]
    if not extraData then 
        extraData = {} 
        storage[tb] = extraData 
    end
    -- do stuff with it
end

However, you’ll leak memory, because even once the person who called the library stops using the object your storage table will still be holding onto it. You could force the caller to explicitly call a “delete/destroy” method on your library, but that’s not very nice.

Instead, you can make storage a weak-keyed table. That way when storage is the only reference left, the entry will automatically be removed from the storage table by the garbage collector.

9 Likes

@stravant That is the clear answer I had wished for! @stravant , what exactly is defined as a key? Is a Vector3 a key or a value?

Keys are what you access a table with; they can be any value that is not nil or NaN.

table.key = value
-- or
table[key] = value

Lua collects garbage without strong references, so when your mode is k, if your key in the table doesn’t have any other references it’ll get collected.

1 Like

It should be noted that values and keys which are evaluated by value and not identity (strings, numbers, booleans) will act like they are always referenced. If your table had weak keys and you used the number [1] as a key, that key/value in the table would not be garbage collected.

functions, userdatas (instances and Roblox data types), threads, and tables are all evaluated by identity and function as expected in weak tables.

1 Like