Hi. It looks like this topic has been quiet for a month, so maybe you’re an expert by now, but since it was in the “From the Forum” blog post…
I’ll just throw out some links to code and a little snippet or explanation. If desired, I could probably hunt down some of the actual usage later (where there is any; some of these are either legacy or preparatory).
On the numbers front, you can iterate over the powers of 2 of a number as
local powers = require("bitwise\_ops.powers\_of\_2") for \_, power, bit in powers.PowersOf2(23) do -- = 1 + 2 + 4 + 16 print(power, bit) end -- Results: 16, 4; 4, 2; 2, 1; 1, 0
or iterate over the first n Gray codes (consecutive numbers that only change by one bit):
local gray = require("number\_ops.gray") for num in gray.FirstN(100) do print(num) end
The following iterator behaves like ipairs , but is ignored if the table is nil : IpairsIf
And in that same file, for pairs : PairsIf, which is slightly overloaded to also allow filtering on value type (“table”, “number”, etc.).
Here’s a coroutine-based iterator (used throughout the same file): BlockIter (the non-standard wrap just puts the coroutine body in a loop, whereas it would otherwise be one-shot)
Here’s some iteration over what I’ve called adaptive arrays and adaptive sets (the latter is a misnomer… I’ll rename this to dictionary or map). Basically, these are values that are either nil (unassigned, so far), a non-table (one item assigned), or a table (multiple items assigned), but which can be iterated over without needing to know.
Finally, some stateful iterators (i.e. some information needs to be stored specifically in order to maintain the iterator). This stuff is a little more framework-heavy, being largely built on top of this (which I rambled on about here).
I forget the exact justification of the coroutine one, so I’ll skip that.
The args stuff can be used to iterate varargs (n.b. NOT the arg table, which is deprecated in stock Lua):
local args = require("iterator\_ops.Args") for i, v in args.Args("a", nil, 20, 30, true, false, "BOB") do print(i, v) -- prints 1, "a"; 2, nil; 3, 20; etc. end local function P (...) for i, v in args.Args(...) do print(i, v) -- prints 1, "d"; 2, "p" end end P("d", "p") for i, a, b, c in args.ArgsByN(3, "a", "b", "c", 1, 2, 3, "x", "y", "z" ) do print(i, a, b, c) -- prints 1, "a", "b", "c"; 2, 1, 2, 3; 3, "x", "y", "z" end
The ipairs stuff is motivated by the occasional circumstance where you have some logic that’s shared by an array and a separate item, and it would be more convenient to streamline the use:
local ipairs\_ex = require("iterator\_ops.ipairs") -- Instead of... -- for i, v in ipairs(t) do -- GINORMOUS block of code -- end -- -- Same block of code, mostly repeated for item -- ...do this... for i, v in ipairs\_ex.IpairsThenItem(t, item) do if i then DoArraySpecificThing(t, i) else DoItemSpecificThing(item) end -- Big block of code, just once end ...or this. for i, v in ipairs\_ex.ItemThenIpairs(item, t) do -- Big block end
Too much typing, so I’ll just point out that I also have some iterators for grid-based shapes, over an array-ish class, and over timeouts.