lua-users home
lua-l archive

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


> The problem with table.pack is it lacks functionality that is very
> complicated and expensive in pure Lua. Packing values into a new table
> is easy (the common idiom: {n = select("#", ...); ...}). Packing
> values into an existing table is hard. You must iterate over the
> vararg using select which is expensive and ugly. As I've said
> elsewhere, what we really need is table.pack to work on a table passed
> to it and take an index on where to append the values to the array
> (usually, the very beginning). Something like this captures all use
> cases I can think of:
>
> table.pack(t, n, ...)
>
> where the length of t is truncated to length n-1 (luaH_resize?) and
> the variable number of arguments are appended. It may even make sense
> to have an upper bound on where to pack just like table.unpack.

I agree this is useful.

Here's a Lua version with just one select(), though it still has to
evaluate the (diminishing)
vararg on each recursion:

local function Collect (acc, i, count, v1, v2, v3, v4, v5, ...)
	if i <= count then
		acc[i + 1], acc[i + 2], acc[i + 3], acc[i + 4], acc[i + 5] = v1, v2,
v3, v4, v5

		return Collect(acc, i + 5, count, ...)
	end

	return count, acc
end

--- Collects arguments, including <b>nil</b>s, into an object.
-- @param acc Accumulator object; if <b>nil</b>, a table is supplied.
-- @param ... Arguments to collect.
-- @return Argument count.
-- @return Filled accumulator.
function CollectArgsInto (acc, ...)
	local count = select("#", ...)

	if acc then
		return Collect(acc, 0, count, ...)
	else
		return count, { ... }
	end
end

By adjusting 0 and count passed to the first Collect() it should
accommodate an offset, too.

(5 values seemed to do best during testing.)