• Subject: Re: pairs and ipairs
• From: Francisco Olarte <folarte@...>
• Date: Mon, 23 Oct 2023 10:00:31 +0200

```On Sun, 22 Oct 2023 at 22:15, Petite Abeille <petite.abeille@gmail.com> wrote:
> local function kpairs( aTable )
>   local aLength = 0 -- #aTable ~= ipairs( aTable )
>
>   for anIndex, _ in ipairs( aTable ) do
>     aLength = anIndex
>   end
>
>   return coroutine.wrap
>   (
>     function()
>       for aKey, aValue in pairs( aTable ) do
>         if not ( math.type( aKey ) == 'integer' and aKey >= 1 and aKey <= aLength ) then coroutine.yield( aKey, aValue ) end
>       end
>     end
>   )
> end

Given the language gives you mechanism to build loops, generators (
this coroutine looks like a generator in disguise ) are a bit overkill
for just an iterator:
>>>>
local function kpairs( aTable )
local aNext = 1
while aTable[aNext] ~= nil do
aNext = aNext+1
end

local function kNext(t,k)
local v;
k,v = next(t,k)
-- Extra advantage of un-negating the condition ( IMO )
while math.type(k)=="integer" and k>=1 and k<aNext do
k,v = next(t,k)
end
return k,v
end

return kNext,    aTable, nil
end
<<<
The closure could be zapped by using { aTable, aNext } as the state,
but hey, this is not C.

Given the language does the boring stuff of looping, I in general
prefer to do these things by customizing the next/state stuff. This
kind of construct appear so much that I have things like this sitting
around:
>>>>
local function pred_next(pred, t,lastk)
local k,v = next(t,lastk)
while k ~= nil and not pred(t,k,v) do
k,v = next(t,k)
end
return k,v
end

local function make_next(pred)
return function(...)
return pred_next(pred,...)
end
end

local function pkpairs(aTable)
local aNext = 1
while aTable[aNext] ~= nil do
aNext = aNext+1
end

local function not_in_list(_t,k,_v)
return not (math.type(k)=="integer" and k>=1 and k<aNext)
end

return make_next(not_in_list),aTable,nil
end
<<<<

Francisco Olarte.

```