[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Abolishing the numeric-for
- From: Jonathan Castello <twisolar@...>
- Date: Mon, 24 May 2010 16:25:48 -0700
On Mon, May 24, 2010 at 4:09 PM, M Joonas Pihlaja
<jpihlaja@cc.helsinki.fi> wrote:
> This particular generic-for proposal doesn't work for basic iterators
> which follow the current iterator protocol. For example, it would try
> to run pairs() on the function "next" if we were to give it this:
>
> for k,v in next, sometable do
> print(k,v)
> end
>
> In lua 5.1 that's equivalent to "for k,v in pairs(sometable) do
> print(k,v) end".
>
I wrote a function that implements the algorithm in pure Lua. The
function body comes first, so all of the arguments from iterator
factories like pairs() will be sent as parameters, but beyond that it
seems to work perfectly.
----
function meta_for(...)
local params = {...}
local body = table.remove(params, 1)
local object = table.remove(params, 1)
local obj_meta = debug.getmetatable(object)
if type(object) == "number" and
not obj_meta or (obj_meta and not obj_meta.__iter) then
local var = tonumber(object)
local limit = tonumber(params[1])
local step = tonumber(params[2])
for i=var,limit,step do
body(i)
end
else
local f, s, var
if obj_meta and obj_meta.__iter then
f, s, var = obj_meta.__iter(object, params)
elseif type(object) == "table" then
f, s, var = pairs(object, params)
else
f, s, var = object, params[1], params[2]
end
while true do
local results = {f(s, var)}
var = results[1]
if var == nil then break end
body(unpack(results))
end
end
end
----
Usage:
meta_for(function(k, v)
print(k, v)
end, {1, 1, 2, 3, 5})
--[[
Equivalent to
for k,v in {1, 1, 2, 3, 5} do
print(k, v)
end
--]]
Output:
1 1
2 1
3 2
4 3
5 5
Numeric works too: meta_for(function(i) print(i) end, 100, 10, -5)
As a slightly interesting point, you can do this, too:
function range(min, max)
return min, max, 1
end
meta_for(function(i) print(i) end, range(1, 10))
> The key point is that the _compiler_ can't know in advance whether
> you're going to give numbers some wacky __iter metamethod before you
> actually run the loop, so you're going to have to check for __iter on
> numbers every time you begin a loop, just like in your pseudocode
> above. By the time the interpreter wants to run your loop it's too
> late to do any optimisation.
I don't really know enough about the Lua bytecode compiler to comment
further, sorry
~Jonathan