Page 8 of 8

Re: What techniques that everyone should know?

Posted: Tue Apr 01, 2014 9:05 pm
by kikito
If you move the if outside the loop, the function gets shorter:

Code: Select all

function shallowCopy(t)
    if type(t) ~= 'table' then return t end
    local result = {}
    for k, v in pairs(t) do
      result[k] = shallowCopy(v)
    end
    return result
end
Now let's add another level there: Keys can be tables, too:

Code: Select all

function shallowCopy(t)
    if type(t) ~= "table" then return t end
    local result = {}
    for k, v in pairs(t) do
      result[shallowCopy(k)] = shallowCopy(v)
    end
    return result
end
Finally, tables containing loops will make the function loop infinitely. The only way I've found to handle that is to parse the table in advance, looking for loops, and handling those differently than the default tables. But the code to handle that case is a bit long and boring.

Re: What techniques that everyone should know?

Posted: Tue Apr 01, 2014 9:10 pm
by HugoBDesigner
tio wrote:
Zarty55 wrote:I'm not sure if this would make a shallow copy of a table, but I will put it here:

Code: Select all

function copyTable(t)
  return {unpack(t)}
end
Robin wrote:Yes, but it will make a shallow copy of a sequence. If your table contains any non-sequence key/value pairs and you want to copy those too, you'd use:

Code: Select all

function shallowCopy(t)
    local n = {}
    for k, v in pairs(t) do
        n[k] = v
    end
    return n
end
Works considering that the table doesn't have any inner tables ;) (It will work, but will point to the tables of the first list, which may not be the desirable behavior).

One option to duplicate these tables too would be a recursive call, like this:

Code: Select all

function shallowCopy(t)
    local n = {}
    for k, v in pairs(t) do
        if type(v) == "table" then
            n[k] = shallowCopy(v)
        else
            n[k] = v
        end
    end
    return n
end
I made this function once. But I made the sub-tables copy thing optional. Instead of making it always copy tables (sometimes I wanted to change those tables, not their copies), I made this:

Code: Select all

function shallowCopy(t, sub)
    local sub = sub or false
    local n = {}
    for k, v in pairs(t) do
        if type(v) == "table" and sub then
            n[k] = shallowCopy(v, true)
        else
            n[k] = v
        end
    end
    return n
end

Re: What techniques that everyone should know?

Posted: Tue Apr 01, 2014 9:36 pm
by tio
kikito wrote:(...)
Finally, tables containing loops will make the function loop infinitely. The only way I've found to handle that is to parse the table in advance, looking for loops, and handling those differently than the default tables. But the code to handle that case is a bit long and boring.
How can a Lua table have a loop?

Re: What techniques that everyone should know?

Posted: Tue Apr 01, 2014 10:03 pm
by Nixola

Code: Select all

>math.math = math
>print(math.math.math.math.math.math.math.sin(0))
1

Re: What techniques that everyone should know?

Posted: Tue Apr 01, 2014 11:56 pm
by tio
Nixola wrote:

Code: Select all

>math.math = math
>print(math.math.math.math.math.math.math.sin(0))
1
I din't know it was possible :o:
Thanks for the tip :nyu:

Re: What techniques that everyone should know?

Posted: Wed Apr 02, 2014 12:31 am
by Robin
Hint: we were talking about shallow copies. ;)

My function was correct.

If you want a deep copy, I'd suggest this:

Code: Select all

function deepcopy(t, cache)
    if type(t) ~= 'table' then
        return t
    end

    cache = cache or {}
    if cache[t] then
        return cache[t]
    end

    local new = {}

    cache[t] = new

    for key, value in pairs(t) do
        new[deepcopy(key, cache)] = deepcopy(value, cache)
    end

    return new
end
This deals correctly with tables forming any graph, not just trees.

Also, neither touches metatables. If you want them metatables, you have to decide if you want to copy those as well, or just do something like setmetatable(new, getmetatable(t)).