lua-users home
lua-l archive

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


There were some posts a few days ago that were nested several deep in a discussion on ipairs [1], in which the idea was brought up of using a different approach to metamethods for the generic for than the current working proposal of __pairs and __ipairs. I felt that the idea should be brought to the forefront, so I've written up a more formal "proposal".

The way I'd conceptualized it was that, when the generic-for encountered an iterator that wasn't a function, before raising an error, it would first check the metatable for a function at the "__iter" index. If it found a function there, it would use it, allowing users to override the iterative behavior over an object more simply than overriding its functionality when passed to pairs() (or ipairs, even though the manual suggests it should be deprecated).

Additionally, you could use this to bring back the "for k,v in t do" syntax by making the default function for tables be next() in the event they don't have an __iter metamethod.

To put the original concept in terms of the Lua manual's definitions for metamethods:

function generic_for_iterate (iter, ...)
if ... then -- if the iteration has not completed (iterator hasn't returned nil)
    if type(iter) == "function" then -- got iterator?
return generic_for_iterate(iter,iter(...)) --continue iterating with it
    else -- got some
      meta_iter = metatable(iter).__iter
      if meta_iter then -- metatable has iterator?
return generic_for_iterate(meta_iter,meta_iter(iter)) -- start iterating with metatable's iterator
      elseif type(iter) == "table" then -- default case for tables
return generic_for_iterate(next,next(iter)) -- start iterating with the default iterator
      else --no iterator available: default behavior
error("this was an ellipsis in the original manual but I couldn't copy it correctly")
      end
    end
  end
end

Note that I'm not the king of generic for iteration, and if this appears to change the semantics of generic for iterators, that is unintentional. The goal was to show the logic flow for selecting an iterator with metamethods. (It also assumes generic_for_iterate only proceeds after the code inside the loop has been evaluated, of course.)

[1] http://lua-users.org/lists/lua-l/2010-05/msg00581.html