lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

2010/1/10 Mark Hamburg <>
On Jan 9, 2010, at 1:52 AM, Alexander Gladysh wrote:

>> Mark's remark
>> about pack/unpack being paired has some relevance here: pack() must
>> set 'n', so why can't unpack() use it? Or ipairs?
> And we're back to 4.x times?
> I guess the problem is that if you accidentally have the "n" field
> that is totally unrelated to the table size (which is and must be a
> perfectly legal thing to do), you would not be able to do *anything*
> (aside of changing the table) to prevent unpack() or ipairs() from
> looking at it.
> If we're going this way, then, better solution, perhaps, would be to
> have a custom length "attribute" on a table, which would not be
> neither a key nor a value.
> But wait, now we're have one! The __len metamethod! Of course, this
> has overhead of dealing with metatables, but, then, see (1).

Yes, n is problematic because it isn't going to work with idioms like t[ #t +  1 ]  = x.

On the other hand, if the goal of pack is to pair with unpack, then it would be nice if they paired well. Right now, one needs to write:

       x = table.pack( ... )

       -- some time later

       table.unpack( x, 1, x.n )

That seems unbalanced.

Note that my proposal to have unpack look for n is only if the range isn't provided, so one could always write unpack( t, 1, #t ) to get the current behavior.

Another option is a separate pair of functions: packn and unpackn.

Or maybe pack sets a metatable that implements __len, but then beware of insertions as noted above.


table.pack seems a very strange function to me: its a one liner in lua, and shouldn't be any faster to code in C...
function table.pack ( ... ) return { n= select ( "#",...) , ... } end
==> I thought in general the lua devs/community were quite against including simple "batteries" like this.

on the other hand, if it actually set __len on the returned table to be the number of varargs, that would be much more useful (and of course, unpack would need to respect it):
function table.pack ( ... )
  local n = select ( "#" , ... )
  return setmetatable ( { ... } , {
    __len = function ( t )
      local l = rawlen ( t )
      if l > n then return l
      else return n
    end ;
I do NOT approve of this idea/implementation: and I can see many complications. BUT, I think it would be the only good use of a table.pack