lua-users home
lua-l archive

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


On Wed, Jan 11, 2017 at 01:34:49AM -0800, Chris Lu wrote:
> Hi,
> 
> I am using LuaJIT. I need to pass the result of one function to another
> function. The first function has multiple return values. This is the code I
> am using.
> 
>   local t = {functionFirst()}
>   functionSecond(unpack(t))
> 
> This works mostly, but fails if one of the return value is nil. The first
> function is defined by the end user, so I can not control it.
> 
> How to detect the number of return values? If I can know how many values
> are returned from first function,  this should work.
> 
>   functionSecond(unpack(t, 1, count))
> 
> Thanks!

-- solution #1 - canonical solution used most often
do
	local function packlist(...)
		local t = { ... }
		t.n = select("#", ...)
		return t
	end

	local unpack = table.unpack or unpack
	local function unpacklist(t)
		return unpack(t, 1, t.n)
	end

	print(unpacklist(packlist(1, nil, 2)))
end

-- solution #2 - example using coroutines
do
	local function packlist(...)
		local restore = coroutine.wrap(function (...)
			while true do
				coroutine.yield(...)
			end
		end)
		restore(...) -- prepare coroutine
		return restore
	end

	unpacklist = packlist(1, nil, 2)
	print(unpacklist())
end

-- solution #3 - reuseable coroutine that doesn't instantiate a new table
-- for every return list capture (possibly more performant in some
-- circumstances) but only supports unpacking once
do
	local function packlist(...)
		local function pack_then_unpack(...)
			coroutine.yield() -- pack phase
			return pack_then_unpack(coroutine.yield(...)) -- unpack phase
		end
		local lazyf = coroutine.wrap(pack_then_unpack)
		lazyf() -- start coroutine (noop pack phase)
		lazyf() -- noop unpack phase
		lazyf(...) -- repack
		return lazyf
	end

	unpacklist = packlist(1, nil, 2)
	print(unpacklist())

	unpacklist(nil, nil, nil) -- reinitialize with new set
	print(unpacklist())
end