Difference Between State Iterators and Lost Users in Lua

What is the difference between stateless and stateless iterators in Lua, please explain in detail when we need to use stateless and when another? I need examples to understand the concept.

+4
source share
2 answers

First agree to the definition: (in Lua) an iterator is a function-like object that returns the next value in the sequence for each call. I think this will help rewrite the iteration foras done in the Lua ref manual:

for itemlist in expression do block end

logically equivalent (pseudo-code):

do
    local func, seq, controlVar = expression
    while true do
        local itemlist = func(seq, controlVar)
        if first of itemlist == nil then break end
        controlVar = first of itemlist

        block (which uses items in itemlist)
   end
end

where expressionis the data triplet (or a function call that returns such a triplet):

  • func - actual iterator function
  • seq - ,
  • controlVar -

- , , . , , func : func(seq, controlVar), ( seq ); , .

, Lua . , , . I.e., " s" "(s, controlVar)" . ipairs() , : ipairs(s) (iterFunction, s, 1); iterFunction s 1 2, s[1], 3, s[2] .. ( nil, s[N] N ).

, ? , ? :

  • "" , ;
  • " " , , , .

, . Lua , ( upvalues) (, , .. __call). () () .

. ipairs:

function statefulIpairs(s)
    local f, s, var = ipairs(s)
    return function() 
        local i, v = f(s,var)
        var = i
        return i, v
    end
end

tbl = {'a', 'b', 'c', 'd'}
sip = statefulIpairs(tbl) -- sip is stateful iter specific to tbl
for i,v in sip() do print(i,v) end

, : API- , . : . , , , non nil, :

function resetableStatefulIpairs(s)
    local f, s, var = ipairs(s)
    local start = var
    return function(a,b,reset)
        if reset ~= nil then var = start; return end        
        local i, v = f(s,var)
        var = i
        return i, v
    end
end

sip = resetableStatefulIpairs(tbl) -- sip is stateful iter specific to tbl
for i,v in sip() do print(i,v) end
sip(nil, nil, true) -- reset it
for i,v in sip() do print(i,v) end

. , , "... 3 " ( @deduplicator):

function iterGen(seq, start)
    local cvar = start or 1
    return function(cmd) 
        if cmd == nil then
            if cvar > #seq then return nil, nil end
            val = seq[cvar]
            cvar = cvar + 1
            return cvar-1, val

        else
            cmd = cmd[1]
            if cmd == 'rewind' then
                cvar = start or 1

            elseif cmd == 'newstart' then
                start = cvar
            end
        end
    end
end

:

> s = {1,2,3,4,5,6,7}
> iter = iterGen(s)
> for i,v in iter do print(i,v); if i==3 then break end  end
1       1
2       2
3       3
> iter {'newstart'} -- save current as the new start pos
> for i,v in iter do print(i,v)  end -- continue till end
4       4
5       5
6       6
7       7
> iter {'rewind'}
> for i,v in iter do print(i,v)  end
4       4
5       5
6       6
7       7
> iter {'rewind'}
> for i,v in iter do print(i,v)  end
4       4
5       5
6       6
7       7

, , , , , , , newstart . .

API- , "" "", , .

+6

:

, , , , . string.gmatch(...).

, , , . pairs(a) ( a, next, __pairs), ipairs ( `__ipairs). , -.

+2

Source: https://habr.com/ru/post/1533984/


All Articles