Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Lua, how to get the tail of an array without copying it?

Tags:

lua

I'm wokring with Lua 5.2, and for the sake of this question, assume that the tables are used exclusively as arrays.

Here's a function that returns the tail of an array (the array minus its first element):

function tail(t)

   if # t <= 1 then
      return nil
   end

   local newtable = {}
   for i, v in ipairs(t) do
      if i > 1 then
          table.insert(newtable, v)
      end
   end

   return newtable
end 

For instance:

prompt> table.concat(tail({10, 23, 8}), ", ")

23, 8

However this is achieved by returning a new copy of the table. Is there a way to avoid the creation of a new table?

I am looking for the equivalent of C's returning a pointer to the next element (t++). Is it possible?

like image 640
rahmu Avatar asked Nov 30 '22 05:11

rahmu


2 Answers

As already explained, this is normally impossible.

However, using metatables, you could implement a tail function that performs what you want without copying all the data, by referencing the original table. The following works for most operations in Lua 5.2, but for example not for table.concat:

function tail(t)
  return setmetatable({}, {
    __index = function(_, k) return t[k+1] end,
    __newindex = function(_, k, v) t[k+1] = v end,
    __len = function(_) return #t-1 end,
    __ipairs = function(_) return 
      function(_, i)
        if i+1==#t then return nil end
        return i+1, t[i+2] end, 
      t, 0 end,
    __pairs = function(t) return ipairs(t) end,
  })
end
like image 144
prapin Avatar answered Dec 05 '22 11:12

prapin


This is the nicest way I know to implement tail(). It makes one new table, but I don't think that's avoidable.

function tail(list)
    return { select(2, unpack(list)) }
end
like image 26
jedediah Avatar answered Dec 05 '22 13:12

jedediah