pack = function (...) return { n = select('#', ...), ... } end
-- used to retrieve args from a continuation
local dummy = function (...) return ... end
local continuation_pack =
function (...)
local args = table.pack(...)
return function (f) return f(unpack(args)) end
end
local continuation_thread =
function (...)
local c =
coroutine.create(
function (...)
-- args have been added
local f = coroutine.yield()
while true do
f = coroutine.yield(f(...))
end
end
)
-- "init" the vararg
coroutine.resume(c, ...)
return function (f) return select(2, coroutine.resume(c, f)) end
end
-- recursive; forward-declare
local reverser_impl_thread = nil
reverser_impl_thread =
function (iter, self, ...)
local args = continuation_thread(iter(self, ...))
-- iteration is over?
if args(dummy) == nil then return end
reverser_impl_thread(iter, self, args(dummy))
coroutine.yield(args(dummy))
end
local reverser_impl_pack = nil
reverser_impl_pack =
function (iter, self, ...)
local args = pack(iter(self, ...))
-- iteration is over?
if args[1] == nil then return end
reverser_impl_pack(iter, self, unpack(args))
coroutine.yield(unpack(args))
end
local reverser_pack =
function (...)
local args = pack(...)
return coroutine.wrap(function () return reverser_impl_pack(unpack(args)) end)
end
local reverser_thread =
function (...)
local args = continuation_thread(...)
return coroutine.wrap(function () return reverser_impl_thread(args(dummy)) end)
end
print('reverser (thread):')
for m in reverser_thread(string.gmatch('cat', '.')) do print(m) end
for i, v in reverser_thread(ipairs({ 'a', 'b', 'c' })) do print(i, v) end
print(('-'):rep(30))
print('reverser (pack): ')
for m in reverser_pack(string.gmatch('cat', '.')) do print(m) end
for i, v in reverser_pack(ipairs({ 'a', 'b', 'c' })) do print(i, v) end