How to do recursive iterators in lua?

Viewed 122

I can usually work out how to code the iterators I want in LUA.

But recursive iterators have me beat.

For example, here's a Python recursive iterator that returns all items in a nested list:

def items(x): 
  if isinstance(x,(list,tuple)):
    for y in x:
      for z in items(y): yield z
  else:
    yield x

for x in items([10,20,[30,[40,50],60],[70,80]]): print(x)

This prints

10
20
30
40
50
60
70
80

But I can't get it going in Lua. I think it is because I don't know how to carry around the state of the recursive traversal from one step in the iteration to the next.

Suggestions?

1 Answers

FP style

local function items(tbl, outer_iter)
   local index = 0
   local function iter()
      index = index + 1
      return tbl[index]
   end
   return
      function ()
         while iter do
            local v = iter()
            if v == nil then
               iter, outer_iter = outer_iter
            elseif type(v) == "table" then
               iter = items(v, iter)
            else
               return v
            end
         end
      end
end

Coroutine style

local function items(tbl)
   return coroutine.wrap(
      function()
         for _, v in ipairs(tbl) do
            if type(v) == "table" then
               local iter = items(v)
               local v = iter()
               while v ~= nil do
                  coroutine.yield(v)
                  v = iter()
               end
            else
               coroutine.yield(v)
            end
         end
      end
   )
end

Usage example:

for x in items{10,20,{30,{},{40,50},60},{70,80}} do
   print(x)
end
Related