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

How do you duplicate a variable's value without using the same memory address?

Asked by 5 years ago
Edited 5 years ago

I thought I understood how a variable worked with a variable being assigned an address in memory where you can store a value, though evidently I don't. I have this small snippet of code here that finds certain combination of numbers that fit into a bigger number. My issue is where if result == 0 then I try to copy the value of priorPath to a different variable completedPath, then add list[i] into the table completedPath, and then store completedPath into another table storing all possible paths. My issue is that any changes to completedPath all show up on priorPath which I don't want to happen. So back to the original question, how do I declare a variable of equal value using a different memory address?

local function testNumber(number, exit)

    if number > exit then return false end

    return exit - number

end



local function getPaths(list, goal, priorPath, paths)

    --print(goal)

    for i = 1, #list do

        local result = testNumber(list[i], goal)

        if result == 0 then

            local completedPath = priorPath

            table.insert(completedPath, list[i])

            table.insert(paths, completedPath)

        elseif result then

            table.insert(priorPath, list[i])

            paths = getPaths(list, goal - list[i], priorPath,   paths)

           end

    end

    return paths

end

Edit: I ended up having to do something stupid like the following, and it worked, any better solutions?

local function testNumber(number, exit)


    if number > exit then return false end

        return exit - number

    end



local function getPaths(list, goal, priorPath, paths)
for i = 1, #list do

    print(list[i])

    local result = testNumber(list[i], goal)

    if result == 0 then

        local newTbl = {}

        for k,l in pairs(priorPath) do

            table.insert(newTbl, l)

        end

        table.insert(newTbl, list[i].." ")

        table.insert(paths, newTbl)

    elseif result then

        local newTbl = {}

        for k,l in pairs(priorPath) do

            table.insert(newTbl, l)

        end

        table.insert(newTbl, list[i])

        paths = getPaths(list, goal - list[i], newTbl, paths)

    end

end

return paths

end

1 answer

Log in to vote
1
Answered by
mattscy 3725 Moderation Voter Community Moderator
5 years ago
Edited 5 years ago

This happens because userdata and table data types are pass-by-reference, while numbers, strings and other data types are pass-by-value. This means that, as you have found, creating new variables will still refer to the same copy of the table. To solve this, there are two options that I know of:

In the case of predetermined tables (for example, a table containing default stats), you can create and return the table from a function to obtain a unique copy of the table every time. For example:

local function GetStats()
    return {
        Money = 5;
        Level = 0
    }
end
local Stats1 = GetStats()
local Stats2 = GetStats()
print(Stats1 == Stats2) --> false

Alternatively, if your table is created/altered while the game is running (in most cases), you can make a function to create a unique copy of the table:

local function DeepCopy(Table)
    local Copy = {}
    for Key, Value in pairs(Table) do
        if type(Value) == "table" then
            Copy[Key] = DeepCopy(Value)
        else
            Copy[Key] = Value
        end
    end
    return Copy
end
local Table1 = {"a", "b", "c"}
local Table2 = DeepCopy(Table1)
print(Table1 == Table2) --> false

Hope this helps!

0
I would assume this behavior varies from language to language? Such that in Java something like an ArrayList might not be a pass-by-reference? climethestair 1663 — 5y
Ad

Answer this question