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

Is there a way to see if a new value was added to a table?

Asked by 9 years ago

I was wondering if there is a metamethod or some other thing that will allow me to see if a new value was added to a table?

--[[Purpose:I'm making a script that is finding npcs with the value "Shop"
and making them into a shop]]--

NPCs={}--Table where the npc's will be stored

function FindNpc()--Will Search Workspace for a humanoid if it finds it then it search for the value "Shop" then insert the NPC to the Table
    for Index,Objects in pairs(game.Workspace:GetChildren()) do
        local FoundHumanoid = Objects:FindFirstChild("Humanoid")
            if FoundHumanoid then
                local FoundShopValue = FoundHumanoid:FindFirstChild("Value")
                if FoundShopValue then
                    if FoundShopValue.Value == "Shop" then
                        table.insert(NPCs,FoundHumanoid.Parent)
                    end
                end
            end
    end
end
FindNpc()
--To be Finished

Edited:

--[[Purpose:I'm making a script that is finding npcs with the value "Shop"
and making them into a shop]]--

NPCs={}--Table where the npc's will be stored
Metatable = {
    __newindex = function(self,index,value)
        print(value)
    end
}

setmetatable(NPCs,Metatable)

function FindNpc()--Will Search Workspace for a humanoid if it finds it then it search for the value "Shop" then insert the NPC to the Table
    for Index,Objects in pairs(game.Workspace:GetChildren()) do
        local FoundHumanoid = Objects:FindFirstChild("Humanoid")
            if FoundHumanoid then
                local FoundShopValue = FoundHumanoid:FindFirstChild("Value")
                if FoundShopValue then
                    if FoundShopValue.Value == "Shop" then
                        table.insert(NPCs,FoundHumanoid.Parent)
                        NPCs.x = "a"-- Y U NO print the value
                    end
                end
            end
    end
end
FindNpc()
--print(NPCs[1])
--To be Finished

If there is a way to see if a value was added to a table if so what is it?

2 answers

Log in to vote
1
Answered by
Unclear 1776 Moderation Voter
9 years ago

The __newindex metamethod should do the trick. It triggers when a new index is added to a table without the use of the function rawset (this suggests that table.insert will not trigger __newindex).

Here's an example that prints out the index and the value when it is set...

local t = { }
setmetatable(t, {
    __newindex = function(self, index, value)
        print(index, "=", value)
    end
})
t.x = "a" --> x = "a"
table.insert(t, "test") --> no output, uses table.insert
t[2] = 2 --> 2 = 2
0
Sorry to ask this but I just learned how to use metatables and I was wondering why did you put "t.x = "a" if there is no x in the table t? kevinnight45 550 — 9y
1
That isn't a metatable question as much as it is a table question. A singular period symbol is what we call "syntactical sugar" for square brackets (so t.x = a is the same as t["x"] = a). By accessing this index which has nothing yet in t and then setting it equal to some value, I trigger the __newindex metamethod. Unclear 1776 — 9y
0
Thanks, and I put the metatable part that you showed me and it won't print.Why? kevinnight45 550 — 9y
1
__newindex has two underscores, not one. All metamethods use two underscores. Unclear 1776 — 9y
Ad
Log in to vote
1
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

Sukinahito's answer is a good, direct answer to the question. (I believe Lua 5.3 even fixes the problem that table.insert ignores metatables -- though since ROBLOX is on 5.1, that's a long, long ways away (you can also fix it yourself))

However, that is not the best approach to take to solve this problem.


There is a concept (that comes largely from Object Oriented Programming) called information hiding in computer science. This means separating the way you use something with the way that it works.

In this case, it would mean that when you're trying to make new NPCs (or remove them, get them, etc) you don't actually use the NPCs table; you instead use a few functions (which are the only way to get to the NPCs table)

This means you can do lots of extra stuff, like responding to a new element, without having a complicated API. It also means you won't confuse the user since there will be an explicitly approved way of getting objects, changing them, making new ones, etc.

This might look like this:

do
    local NPCs = {}
    -- This hides NPCs as a variable after the `end` for this `do` (since it's local)
    -- functions are global, so they can be used outside of the `do end`

    function isNPC( thing )
        for _, obj in pairs(NPCs) do
            if obj == thing then
                return true
            end
        end
        return false
    end

    function newNPC( npc )
        if not isNPC( npc) then
            table.insert(NPCs, npc)
            -- Now do whatever you want to do it:
            Instance.new("NumberValue", npc).Name = "Health"
        end
    end

    function removeNPC( npc )
        assert( isNPC(npc) )
        for i = #NPCs, 1, -1 do
            if NPCs[i] == npc then
                table.remove(NPCs, i)
            end
        end
        assert( not isNPC(npc) )
    end

    function getNPCsNear(point, distance)
        local result = {}
        for _, npc in pairs(NPCs) do
            if (npc.Torso.Position - point).magnitude < distance then
                table.insert(result, npc)
            end
        end
        return result
    end
end

The other nice result of this is that you provide explicit, clear ways that you're allowed to get information.

For instance, in the above, there is no (reasonable) way to get a list of all NPCs.

That's a good thing -- there's no good reason some random part of your script should be able to affect the entire world.

At the same time, you're provided with a neat little function to get everything nearby -- also eliminating the need for that code to ever appear twice in your code elsewhere.

Answer this question