[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: idea: __iter generic-for metamethod
- From: "Stuart P. Bentley" <stuart@...>
- Date: Mon, 24 May 2010 16:27:41 -0700
Here's a rewrite based on the manual's definition of the generic for (a
better approach):
A for statement like
for var_1, ···, var_n in explist do block end
is equivalent to the code:
do
local f, s, var = explist
--proposed addition
if type(f)~= "function" then
local meta_f = metatable(f).__iter
if not meta_f and type(f)=="table" then meta_f = next
if meta_f then f, s, var = meta_f, f, s end
end
while true do
local var_1, ···, var_n = f(s, var)
var = var_1
if var == nil then break end
block
end
end
Hopefully that makes sense.
On Mon, 24 May 2010 15:52:29 -0700, Stuart P. Bentley
<stuart@testtrack4.com> wrote:
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