tags:

views:

2741

answers:

6

Recently I wrote a bit of Lua code something like:

local a = {}
for i = 1, n do
   local copy = a
   -- alter the values in the copy
end

Obviously, that wasn't what I wanted to do since variables hold references to an anonymous table not the values of the table themselves in Lua. This is clearly laid out in Programming in Lua, but I'd forgotten about it.

So the question is what should I write instead of copy = a to get a copy of the values in a?

+1  A: 

Here's what I actually did:

for j,x in ipairs(a) do copy[j] = x end

I also found a deepcopy function that is more robust.

If there are better answers, I'd love to see them. Until recently, I've been using a function I wrote myself to perform the functionality of table.concat!

Jon Ericson
+1  A: 

That's as good as you'll get for basic tables. Use something like deepcopy if you need to copy tables with metatables.

Aaron Saarela
+3  A: 

Simply create a new table and duplicate all key/value pairs:

function table.copy(t)
  local t2 = {}
  for k,v in pairs(t) do
    t2[k] = v
  end
  return t2
end

copy = table.copy(a)

Note that you should use pairs instead of ipairs, since ipairs only iterate over a subset of the table keys (ie. consecutive positive integer keys starting at one in increasing order).

Doub
That's a good hint about pairs. It surprises me that table.copy (or something very much like it) would need to be coded by hand and is not included in the standard library. Thank you for the advice.
Jon Ericson
Table copy has many potential definitions. It depends on whethere you want simple or deep copy, whether you want to copy, share or ignore metatables, etc. There is no single implementation that could satisfy everybody.
Doub
+3  A: 

The (unfortunately lightly documented) stdlib project has a number of valuable extensions to several of the libraries shipped with the standard Lua distribution. Among them are several variations on the theme of table copying and merging.

This library is also included in the Lua for Windows distribution, and should probably be a part of any serious Lua user's toolbox.

One thing to make sure of when implementing things like this by hand is the proper handling of metatables. For simple table-as-structure applications you probably don't have any metatables, and a simple loop using pairs() is an acceptable answer. But if the table is used as a tree, or contains circular references, or has metatables, then things get more complex.

RBerteig
+1  A: 

I think the reason why Lua doesn't have 'table.copy()' in its standard libraries is because the task is not precise to define. As shown already here, one can either make a copy "one level deep" (which you did), a deepcopy with or without caring of possible duplicate references. And then there's metatables.

Personally, I would still like them to offer a built-in function. Only if people wouldn't be pleased with its semantics, they would need to go do it themselves. Not very often, though, one actually has the copy-by-value need.

akauppi
+3  A: 

Just to illustrate the point, my personal table.copy also pays attention to metatables:

function table.copy(t)
  local u = { }
  for k, v in pairs(t) do u[k] = v end
  return setmetatable(u, getmetatable(t))
end

There is no copy function sufficiently widely agreed upon to be called "standard".

Norman Ramsey