I need some input on... things...

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

I need some input on... things...

Soni "They/Them" L.
Hello, So I have this code for copying tables: (and table-based objects
which don't rely on metatables) local function copy(inp,copies)
local todo = {[inp] = {}}
copies = type(copies) == "table" and copies or {}
copies[inp] = todo[inp]
-- we can't use pairs or for here because we modify todo
while next(todo) do
local i,o = next(todo)
todo[i] = nil
for k,v in next,i do
if copies[k] ~= nil then
k = copies[k]
elseif type(k) == "table" then
local t = {}
todo[k] = t
copies[k] = t
k = t
end
if copies[v] ~= nil then
v = copies[v]
elseif type(v) == "table" then
local t = {}
todo[v] = t
copies[v] = t
v = t
end
rawset(o,k,v)
end
end
return copies[inp] -- heh :P
end People told me to use pairs() where I have "for k,v in next,i", to
respect __pairs, I told them __pairs wasn't made to make copies of
things. Now the questions: Should I do it raw, but respect metatabled
`copies`? Should I do it ALL raw? Or should I do it raw, respect
metatabled `copies`, and look for a __copy metamethod? (Obviously,
copies' metatable would override __copy. This also has the side-effect
of supporting userdata copying!) Is it bad to copy tables and objects
the way I'm doing it? This algorithm is optimized for tables with long
chains, but not many table entries. As in, it's more (space) efficient
for a.b.c.d.e.f.g = {} vs a={{},{},{},{},{}}. I also have another
algorithm which is optimized for the latter. Both can be found here:
https://gist.github.com/SoniEx2/fc5d3614614e4e3fe131 This algorithm
would use only 1 `todo` entry for the a.b.c.d.e.f.g = {} case, and 5 for
the a={{},{},{},{},{}} case. The other algorithm would use 7 call stack
entries for the former case and 2 for the latter case. Is it possible to
make an algorithm which's efficient for both cases? (Please note, this
is all just a guess) Would LuaJIT be able to optimize this?


Reply | Threaded
Open this post in threaded view
|

Re: I need some input on... things...

Steven Degutis
Fwiw, I've made a gist out of this code so I can read it better:

https://gist.github.com/anonymous/b66c3d75efb20cdc2e2f

Quoth Thiago L.:
> [ tons of unformatted code ]

Reply | Threaded
Open this post in threaded view
|

Re: I need some input on... things...

Soni "They/Them" L.

On 17/09/14 01:28 PM, Steven Degutis wrote:
> Fwiw, I've made a gist out of this code so I can read it better:
>
> https://gist.github.com/anonymous/b66c3d75efb20cdc2e2f
>
> Quoth Thiago L.:
>> [ tons of unformatted code ]
Uhh... huh...

Seems like my email client broke the formatting :/

Let's try again:

Hello,

So I have this code for copying tables: (and table-based objects which
don't rely on metatables)

local function copy(inp,copies)
   local todo = {[inp] = {}}
   copies = type(copies) == "table" and copies or {}
   copies[inp] = todo[inp]

   -- we can't use pairs or for here because we modify todo
   while next(todo) do
     local i,o = next(todo)
     todo[i] = nil
     for k,v in next,i do
       if copies[k] ~= nil then
         k = copies[k]
       elseif type(k) == "table" then
         local t = {}
         todo[k] = t
         copies[k] = t
         k = t
       end
       if copies[v] ~= nil then
         v = copies[v]
       elseif type(v) == "table" then
         local t = {}
         todo[v] = t
         copies[v] = t
         v = t
       end
       rawset(o,k,v)
     end
   end
   return copies[inp] -- heh :P
end

People told me to use pairs() where I have "for k,v in next,i", to
respect __pairs, I told them __pairs wasn't made to make copies of things.

Now the questions:

Should I do it raw, and respect metatabled `copies`? Should I do it ALL
raw? Or should I do it raw, respect metatabled `copies`, and look for a
__copy metamethod? (Obviously, copies' metatable would override __copy.
This also has the side-effect of supporting userdata copying!)

Is it bad to copy tables and objects the way I'm doing it?

This algorithm is optimized for tables with long chains, but not many
table entries. As in, it's more (space) efficient for a.b.c.d.e.f.g = {}
vs a={{},{},{},{},{}}. I also have another algorithm which is optimized
for the latter. Both can be found here:
https://gist.github.com/SoniEx2/fc5d3614614e4e3fe131
This algorithm would use only 1 `todo` entry for the a.b.c.d.e.f.g = {}
case, and 5 for the a={{},{},{},{},{}} case. The other algorithm would
use 7 call stack entries for the former case and 2 for the latter case.
Is it possible to make an algorithm which's efficient for both cases?
(Please note, this is all just a guess)

Would LuaJIT be able to optimize this?