@eryx/iter Module

Utilities for working with sequence-like data through a small iterator API.

Functions in this library accept three kinds of iterable input:

  1. Dense array-like tables such as { "a", "b", "c" }
  2. Simple iterator functions of the form () -> (index?, value)
  3. Tables or userdata with an __iter metamethod

Most transforming helpers return a SimpleIterator, which is a stateful iterator function yielding (index, value) pairs until it returns nil.

Use this library when you want to write code against "something iterable" without caring whether the source is an array, an iterator callback, or a custom object with __iter.

Sequence-style transforms such as filter, unique, and reverse produce dense array-like results or dense iterator indices. flatten, by contrast, preserves the yielded numeric keys from the underlying iterable.

local iter = require("@eryx/iter")

local evens = iter.filter({ 1, 2, 3, 4, 5, 6 }, function(value)
    return value % 2 == 0
end)

for index, value in evens do
    print(index, value) -- 1 2, then 2 4, then 3 6
end
local iter = require("@eryx/iter")

local values = iter.reverse(
    iter.unique(
        iter.map({ "pear", "apple", "pear", "plum" }, string.upper)
    )
)

print(values) -- { "PLUM", "APPLE", "PEAR" }

Summary

Classes

Functions

iter.map<T, U, I>(iterable: Iterable<T, I>, mapper: ((T) → U))SimpleIterator<U>
iter.filter<T, I>(iterable: Iterable<T, I>, filter: ((T) → boolean))SimpleIterator<T>
iter.forEach<T, I>(iterable: Iterable<T, I>, callback: ((T) → ()) | ((T, number) → ()))()
iter.flatten<T, I>(iterable: Iterable<T, I>){ T }
iter.generator<T>(fn: (() → ()))SimpleIterator<T>
iter.tableIterator<T>(array: { T })SimpleIterator<T>
iter.reverse<T, I>(iterable: SimpleIterator<T> | MetaIterator<T, I>, inPlace: false?){ T }
iter.unique<T, I>(iterable: Iterable<T, I>)SimpleIterator<T>
iter.find<T>(iterable: { T }, match: ((T) → boolean), start: number?)(number?, T)
iter.reduce<T, U, I>(iterable: Iterable<T, I>, reducer: ((U, T) → U), initial: U)U
iter.all<T, I>(iterable: Iterable<T, I>, match: ((T) → boolean))boolean
iter.any<T, I>(iterable: Iterable<T, I>, match: ((T) → boolean))boolean
iter.permutations<T>(items: { T }, n: number?)SimpleIterator<{ T }>
iter.combinations<T>(items: { T }, n: number)SimpleIterator<{ T }>
iter.product<T>(...: { T })SimpleIterator<{ T }>

API Reference

Classes

MetaIterator<T, Invariant>

Any table that has an __iter metamethod

Properties

Functions

iter.map

Lazily maps each item in an iterable.

iter.map<T, U, I>(iterable: Iterable<T, I>, mapper: ((T) → U))SimpleIterator<U>

Parameters

iterable: Iterable<T, I>

Iterable source to read from.

mapper: ((T) → U)

Transform applied to each yielded value.

Returns

Iterator that yields the original index with the mapped value.

iter.filter

Lazily filters an iterable by predicate. Matching items are reindexed densely from 1.

iter.filter<T, I>(iterable: Iterable<T, I>, filter: ((T) → boolean))SimpleIterator<T>

Parameters

iterable: Iterable<T, I>

Iterable source to read from.

filter: ((T) → boolean)

Predicate used to decide whether an item should be yielded.

Returns

Iterator that yields only items matching filter.

iter.forEach

Calls a function on every item in an iterable

iter.forEach<T, I>(iterable: Iterable<T, I>, callback: ((T) → ()) | ((T, number) → ()))()

Parameters

iterable: Iterable<T, I>

Iterable source to read from.

callback: ((T) → ()) | ((T, number) → ())

Callback called with each yielded value and its index.

iter.flatten

Materializes an iterable into an array. Table inputs are returned directly without cloning. Iterator inputs preserve their yielded numeric keys, which may produce a sparse table.

iter.flatten<T, I>(iterable: Iterable<T, I>){ T }

Parameters

iterable: Iterable<T, I>

Iterable source to flatten.

Returns

{ T }

Array containing all yielded values, keyed by their yielded indices.

iter.generator

Helper for writing coroutine.yield-based generators.

For example:

local function foo()
	return iter.generator(function()
		coroutine.yield(1)
		coroutine.yield(2)
		coroutine.yield(3)
	end)
end
for i in foo() do
	print(i)  -- Prints `1` then `2` then `3`
end
iter.generator<T>(fn: (() → ()))SimpleIterator<T>

Parameters

fn: (() → ())

The yield-based generator

Returns

A Luau-compatible iterator

iter.tableIterator

Converts an array into a stateful iterator function.

iter.tableIterator<T>(array: { T })SimpleIterator<T>

Parameters

array: { T }

Array to iterate over.

Returns

Iterator that yields sequential array indices and values.

iter.reverse

Returns a reversed array. Table inputs may be reversed in place; iterator inputs are collected densely first.

iter.reverse<T, I>(iterable: SimpleIterator<T> | MetaIterator<T, I>, inPlace: false?){ T }

Parameters

iterable: SimpleIterator<T> | MetaIterator<T, I>

Iterable source to reverse.

Returns

{ T }

Reversed array.

iter.reverse<T>(iterable: { T }, inPlace: boolean?){ T }

Parameters

iterable: { T }

Iterable source to reverse.

inPlace: boolean?

When true reverse the table in place.

Returns

{ T }

Reversed array.

iter.unique

Lazily yields only the first occurrence of each distinct value. Yielded items are reindexed densely from 1. Duplicate detection is based on direct Lua equality and table-key semantics.

iter.unique<T, I>(iterable: Iterable<T, I>)SimpleIterator<T>

Parameters

iterable: Iterable<T, I>

Iterable source to deduplicate.

Returns

Iterator that skips values that have already been seen.

iter.find

Finds the first item matching a predicate. For table inputs, start can be used to resume searching from a later index. For iterator inputs, calling this consumes items until a match is found or the iterator ends.

iter.find<T>(iterable: { T }, match: ((T) → boolean), start: number?)(number?, T)

Parameters

iterable: { T }

Iterable source to search.

match: ((T) → boolean)

Predicate used to test each item.

start: number?

Starting index.

Returns

number?

Matching index and value, or nil if no match is found.

iter.find<T, I>(iterable: SimpleIterator<T> | MetaIterator<T, I>, match: ((T) → boolean))(number?, T)

Parameters

iterable: SimpleIterator<T> | MetaIterator<T, I>

Iterable source to search.

match: ((T) → boolean)

Predicate used to test each item.

Returns

number?

Matching index and value, or nil if no match is found.

iter.reduce

Reduces an iterable into a single value.

iter.reduce<T, U, I>(iterable: Iterable<T, I>, reducer: ((U, T) → U), initial: U)U

Parameters

iterable: Iterable<T, I>

Iterable source to reduce.

reducer: ((U, T) → U)

Accumulator function called with the current reduced value and next item.

initial: U

Initial accumulator value.

Returns

U

Final reduced value.

iter.all

Returns whether every item in the iterable matches a predicate.

iter.all<T, I>(iterable: Iterable<T, I>, match: ((T) → boolean))boolean

Parameters

iterable: Iterable<T, I>

Iterable source to test.

match: ((T) → boolean)

Predicate used to test each item.

Returns

boolean

true when all yielded items match, otherwise false.

iter.any

Returns whether any item in the iterable matches a predicate.

iter.any<T, I>(iterable: Iterable<T, I>, match: ((T) → boolean))boolean

Parameters

iterable: Iterable<T, I>

Iterable source to test.

match: ((T) → boolean)

Predicate used to test each item.

Returns

boolean

true when any yielded item matches, otherwise false.

iter.permutations

Yields successive n-length permutations of elements from items.

Order matters: { "a", "b" } and { "b", "a" } are distinct permutations. Each yielded value is a new array. When n equals #items (the default), every possible ordering of the whole sequence is produced.

for _, perm in iter.permutations({ "a", "b", "c" }) do
    print(table.concat(perm, ""))
    -- abc, acb, bac, bca, cab, cba
end
for _, perm in iter.permutations({ 1, 2, 3, 4 }, 2) do
    print(table.concat(perm, ""))
    -- 12, 13, 14, 21, 23, 24, 31, 32, 34, 41, 42, 43
end
iter.permutations<T>(items: { T }, n: number?)SimpleIterator<{ T }>

Parameters

items: { T }

Source array to draw elements from.

n: number?

Length of each permutation. Defaults to #items. Must be non-negative and no greater than #items.

Returns

Iterator that yields (index, permutation) pairs until all permutations are exhausted.

iter.combinations

Yields successive n-length combinations of elements from items, without replacement.

Order does not matter: { "a", "b" } and { "b", "a" } are the same combination and only the first is yielded. Combinations are emitted in lexicographic order relative to the position of each element in the source array. Each yielded value is a new array.

for _, combo in iter.combinations({ "a", "b", "c", "d" }, 2) do
    print(table.concat(combo, ""))
    -- ab, ac, ad, bc, bd, cd
end
iter.combinations<T>(items: { T }, n: number)SimpleIterator<{ T }>

Parameters

items: { T }

Source array to draw elements from.

n: number

Length of each combination. Must be non-negative and no greater than #items.

Returns

Iterator that yields (index, combination) pairs until all combinations are exhausted.

iter.product

Yields the Cartesian product of one or more arrays.

Each yielded tuple contains one element chosen from each input array, in the order the arrays were passed. The rightmost array advances fastest. If any input array is empty, no tuples are produced. Each yielded value is a new array.

for _, pair in iter.product({ "x", "y" }, { 1, 2, 3 }) do
    print(pair[1], pair[2])
    -- x 1, x 2, x 3, y 1, y 2, y 3
end
-- Repeating the same pool simulates combinations with replacement
for _, pair in iter.product({ 1, 2, 3 }, { 1, 2, 3 }) do
    print(pair[1], pair[2])
    -- 1 1, 1 2, 1 3, 2 1, 2 2, 2 3, 3 1, 3 2, 3 3
end
iter.product<T>(...: { T })SimpleIterator<{ T }>

Parameters

...: { T }

One or more source arrays. All elements must share the same type T.

Returns

Iterator that yields (index, tuple) pairs covering every combination across all input arrays.

Types

SimpleIterator<T>

A stateful iterator function yielding (index, value) pairs until it returns nil.

type SimpleIterator<T> = (() → (number?, T))

Iterable<T, Invariant>

An array, a SimpleIterator, or any value with an __iter metamethod.

type Iterable<T, Invariant> = { T } | SimpleIterator<T> | MetaIterator<T, Invariant>