Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How would you check if a table was changed?

Asked by 8 years ago

I have a code that displays the number of blocks that are in a field (field is a table), and how many blocks left until the field is empty. I am currently stuck with how to check when the table updates. I could use while do loops, but I want to avoid those

2 answers

Log in to vote
7
Answered by 8 years ago

Metatables! (and metamethods :D)

What you're looking for is the __newindex metamethod. Metamethods are like events, but for specific tables, called metatables (see metatables: http://wiki.roblox.com/index.php?title=Metatable).

What are metatables?

So what are metatables? There are many analogies of a metatable being "a table inside a table" - though I strongly advise to neglect this description, for I don't find it relevant to what a metatable is at all.


A metatable is more of a secondary table you can attach to a "regular table". The metatable you attach to that regular table, can contain a dictionary of functions that act as events on the table when certain procedures occur. These "events", are obviously referred to as metamethods as explained above (see metamethods: http://wiki.roblox.com/index.php?title=Metamethods)


Check when a table is changed?

Like I initially said, the metamethod you'd use to accomplish this task, would be __newindex. The function you associate with this metamethod will execute whenever a new index is added to the table that the metatable belongs to. But first, let's create the metatable.


Creating a metatable

To create a metatable, we simply use the built-in setmetatable function. This function takes two arguments:

  • 1: The normal table

  • 2: The metatable, with all it's metamethods.

The setmetatable function also returns the normal table, so we can create it in one nice compact variable declaration, like this:

local t = setmetatable({} , {}) -- A blank normal table created, with a blank metatable attached.

How does __newindex work?

Now despite the name, it's important to know that __newindex will only execute if whatever "new index" you're trying to set, **doesn't exist**. This is why it's probably best to ensure you're starting with a blank table, so you can catch all the new keys that are added - if that is your intention.

Now I'm not going to cover all the metamethods - as there are quite a few - so I'll just be going over __newindex. To make this demonstration a bit clearer, I'll separate both the regular table, and the metatable with two different variables:

local normal = {} -- this will be our regular table
local meta = {} -- this will be our metatable
setmetatable(normal,meta) -- boom, now they're attached.

So now let's apply the __newindex metamethod to our "meta" table:

local normal = {}

-- In dictionary format (i.e, having __newindex as the key, and it's function as the value).
local meta = {
    __newindex = function()
    end
}

setmetatable(normal,meta) 

Now the __newindex metamethod takes in 3 parameters:

  • 1) The normal table

  • 2) The key that's trying to be set

  • 3) The value associated with that key

These parameters are often represented using a single letter, just to keep things simple. For example, the first parameter could be t for table, the second could be k for key, and the last could be v for value - however the name of these parameters is completely up to you.


Full example

So now, let's cover a full example of how this would look adding a new index to a table, and watching the __newindex metamethod execute upon doing so:

local normal = {}

local meta = {
    __newindex = function(t,k,v)
        -- This will print when a new key is added to the table
        print("The key: "..tostring(k).." has been added to the table.")
    end
}

setmetatable(normal,meta)

normal.Hello = "Hello world" -- Invokes the __newindex metamethod.

IMPORTANT

Something very important to note here, is that table.insert and table.remove will NOT invoke these metamethods. So having the __newindex metamethod example I created above, will not execute if you inserted a value in the table via table.insert - please remember that.

Questions

Hope that helped, let me know if you have any questions!

Ad
Log in to vote
0
Answered by
Perci1 4988 Trusted Moderation Voter Community Moderator
8 years ago

You have to use metatables. You can think of metatables as events for tables. They look different and work different, but achieve a similar purpose.

This blog post basically gives a complete tutorial, so there's no need for me to repost one. If you're interested, here's the wiki article, although I think the blog post is easier to understand.

One thing to note is that the __ (used before all metamethods) is two underscores. This can be confusing and hard to solve if you don't know about it. You need __, not _

Answer this question