Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Iterators: point me to some good examples?
Started by soggybag Jan 16 2014 12:31 PM

- - - - -
4 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

soggybag

[GLOBAL: userInfoPane.html]
soggybag
  • Starter
  • PipPipPipPipPipPip
  • 253 posts
  • Jedi

Building modules for games those modules invariably contain arrays of objects. Often I need to look through these arrays from other modules. Passing the array back and forth is easy but sloppy and invites errors.

 

What's needed is an iterator. Are there any good examples of setting up iterators in Lua? 



[TOPIC: post.html]
#2

soggybag

[GLOBAL: userInfoPane.html]
soggybag
  • Starter
  • PipPipPipPipPipPip
  • 253 posts
  • Jedi

I had searched for Lua iterators before, and I always came up with pairs and ipairs which is not really hat I was looking for. After a more careful choice of search terms I found this: http://www.troubleshooters.com/codecorn/lua/luaclosures.htm



[TOPIC: post.html]
#3

AlanPlantPot

[GLOBAL: userInfoPane.html]
AlanPlantPot
  • Starter
  • PipPipPipPipPipPip
  • 732 posts
  • Jedi

That's a great article. Even though I do some of these already, there were a few tricks in there that I had never thought of.



[TOPIC: post.html]
#4

StarCrunch

[GLOBAL: userInfoPane.html]
StarCrunch
  • Starter
  • PipPipPipPipPipPip
  • 73 posts
  • Jedi

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.



[TOPIC: post.html]
#5

ksan

[GLOBAL: userInfoPane.html]
ksan
  • Pro
  • PipPipPipPipPipPip
  • 2,637 posts
  • Jedi

Wow! So much information to digest. Thank you very much for sharing. 




[topic_controls]
[/topic_controls]