Skip to content

Instantly share code, notes, and snippets.

@weswigham
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weswigham/53e6f4e4f74376a5c26a to your computer and use it in GitHub Desktop.
Save weswigham/53e6f4e4f74376a5c26a to your computer and use it in GitHub Desktop.
A recursive deepcopy implementation
local copymember = {
['function'] = function(val, memo)
local copy;
local err = pcall(function() --handling the error is faster than getting debug info
copy = loadstring(string.dump(val))
end)
if (not copy) then
memo[val] = val
return val
end
local info = debug.getinfo(val,'u');
if info and info.ups and info.ups>0 then
for i=1,i<info.ups do
debug.setupvalue(copy, i, debug.getupvalue(val, i))
end
end
memo[val] = copy
return copy
end,
['generic'] = function(val, memo)
return val
end
}
setmetatable(copymember, {__call = function(self, val, memo)
if copymember[type(val)] then
return copymember[type(val)](val, memo)
else
return copymember['generic'](val, memo)
end
end})
function deepcopy(orig, memo)
memo = memo or {}
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
memo[orig] = copy
for orig_key, orig_value in next, orig, nil do
copy[memo[orig_key] or deepcopy(orig_key, memo)] = memo[orig_value] or deepcopy(orig_value, memo)
end
setmetatable(copy, memo[getmetatable(orig)] or deepcopy(getmetatable(orig), memo))
else -- number, string, boolean, etc
copy = copymember(orig, memo)
end
return copy
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment