[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: ipairs in Lua 5.3.0-alpha
- From: Jan Behrens <jbe-lua-l@...>
- Date: Fri, 15 Aug 2014 15:44:11 +0200
On Wed, 13 Aug 2014 22:33:23 +0200
Jan Behrens <jbe-lua-l@public-software-group.org> wrote:
> By principle, however, it is not possible to reduce this overhead,
> because the way the for-loop works in Lua, we may only pass one Lua
> value (the second value of the triplet) as state. Unless luaB_ipairs
> creates either a closure or a table that contains the length
> information (and thus the termination point of the iteration), we
> cannot remember the length and will have to redetermine it during every
> iteration step. Creating tables or closures, however, would have an
> even greater perfomance impact.
On Fri, 15 Aug 2014 03:07:16 +0200
Jan Behrens <jbe-lua-l@public-software-group.org> wrote:
> Sorry to bring this up... but... consequently, maybe the global ipairs
> function should be completely removed and replaced by a language
> construct in the long term?
>
> Consider:
>
> for v = t[i] do
> print(i, v)
> end
I just came up with a better idea, which only introduces minimal
changes into the language, but allows a removal of the __ipairs
metamethod, yet avoiding re-evaluating the length for every
iteration step: adjusting Lua's for-statement in such way that more
than one state variable can be passed.
This - at first - looks like it would break downward compatibility.
But it does not.
Lua 5.3.0-alpha works like this:
============================================================
function lua53alpha_for(args)
local f, s, var = table.unpack(args.explist)
local block = args.block
while true do
local results = {f(s, var)}
if results[1] == nil then break end
var = results[1]
block(table.unpack(results))
end
end
do
local function lua53alpha_ipairs_aux(t, i)
print("Evaluating length here!")
if i < #t then
i = i + 1
return i, t[i]
else
return nil
end
end
function lua53alpha_ipairs(t)
return lua53alpha_ipairs_aux, t, 0
end
end
t = {"a", "b", "c"}
lua53alpha_for{explist = {lua53alpha_ipairs(t)}, block = function(i, v)
print(i, v)
end}
-- results in:
-- Evaluating length here!
-- 1 a
-- Evaluating length here!
-- 2 b
-- Evaluating length here!
-- 3 c
-- Evaluating length here!
============================================================
NOTE: Of course, Lua internally doesn't create tables here. I just need
to create tables in the above example code to demonstrate the way
Lua works. It should be understood as pseudocode.
Because Lua 5.3.0-alpha can only deal with one state variable, it needs
to re-evaluate the length in the "lua53alpha_ipairs_aux" function
(calling "luaL_len" in "ipairsaux" in baselib.c).
But why don't we allow more than one state variable?
Consider the following (pseudo)code:
============================================================
function alternate_for(args)
local f = args.explist[1]
local statecount = math.max(1, #args.explist - 2)
local s1_s2_sn_var = {}
local block = args.block
for i = 1, statecount+1 do
s1_s2_sn_var[i] = args.explist[i+1]
end
while true do
local results = {f(table.unpack(s1_s2_sn_var))}
if results[1] == nil then break end
s1_s2_sn_var[statecount+1] = results[1]
block(table.unpack(results))
end
end
do
local function alternate_ipairs_aux(t, maxn, i)
if i < maxn then
i = i + 1
return i, t[i]
else
return nil
end
end
function alternate_ipairs(t)
print("Evaluating length here!")
return alternate_ipairs_aux, t, #t, 0 -- not a triplet but a quadruple
end
end
t = {"a", "b", "c"}
alternate_for{explist = {alternate_ipairs(t)}, block = function(i, v)
print(i, v)
end}
-- results in:
-- Evaluating length here!
-- 1 a
-- 2 b
-- 3 c
-- alternate_for is backwards compatible to lua53alpha_for:
alternate_for{explist = {lua53alpha_ipairs(t)}, block = function(i, v)
print(i, v)
end}
-- results in:
-- Evaluating length here!
-- 1 a
-- Evaluating length here!
-- 2 b
-- Evaluating length here!
-- 3 c
-- Evaluating length here!
============================================================
I'd like to know if this is feasible for Lua 5.3.
Regards
Jan Behrens