Module iterutils

This module imlements operations for iterators and slices. You can see it as a lazy version of sequtils.

The iterators can easily be combined:

for i in filter(map(filter(2..10, proc(x: int): bool = x mod 2 == 0),
         proc(x: int): int = x * 2), proc(x: int): bool = x mod 8 == 0):
  echo i

var s = toSeq (2..10).filter(proc(x): bool = x mod 2 == 0).
        map(proc(x): int = x * 2).filter(proc(x): bool = x mod 8 == 0)
echo s

var a = (2..10).filter(proc(x: int): bool = x mod 2 == 0)
var b = a.map((x: int) => x * 2)
for i in b.map((x: int) => x + 2):
  echo i

Performance example:

Raw implementation with a loop:

# 0.2 s
for i in 1..100_000_000:
  if i mod 2 == 0:
    if i mod 4 == 0:
      if i mod 8 == 0:
        if i mod 16000 == 0:
          echo i div 16

Using sequtils:

# 5.3 s
for i in toSeq(1..100_000_000).
         filter(proc(x): bool = x mod 2 == 0).
         filter(proc(x): bool = x mod 4 == 0).
         filter(proc(x): bool = x mod 8 == 0).
         filter(proc(x): bool = x mod 16000 == 0).
         map(proc(x): int = x div 16):
  echo i

Using iterutils:

# 1.8 s
for i in (1..100_000_000).
         filter(proc(x): bool = x mod 2 == 0).
         filter(proc(x): bool = x mod 4 == 0).
         filter(proc(x): bool = x mod 8 == 0).
         filter(proc(x): bool = x mod 16000 == 0).
         map(proc(x): int = x div 16):
  echo i

Types

Iterable*[T] = (iterator (): T) | Slice[T]
Everything that can be iterated over, iterators and slices so far.   Source

Procs

proc toIter*[T](s: Slice[T]): iterator (): T
Iterate over a slice.   Source
proc toIter*[T](i: iterator (): T): iterator (): T
Nop   Source
proc map*[T, S](i: Iterable[T]; f: proc (x: T): S): iterator (): S
Returns an iterator which applies f to every item in i.
for x in map(2..10, proc(x): int = x * 2):
  echo x

for i in (1..10).map(proc(x): string = "foo: " & $x):
  echo i
  Source
proc filter*[T](i: Iterable[T]; f: proc (x: T): bool): iterator (): T
Iterates through an iterator and yields every item that fulfills the predicate f.
for x in filter(1..11, proc(x): bool = x mod 2 == 0):
  echo x
  Source
proc concat*[T](its: varargs[T, toIter]): iterator (): T
Takes several iterators' items and returns a new iterator from them.
for i in concat(1..4, 20..23):
  echo i
  Source
proc zip*[T, S](i: (iterator (): T) | Slice[T]; j: Iterable[S]): iterator (): tuple[
    a: T, b: S]
Iterates through both iterators at the same time, returning a tuple of both elements as long as neither of the iterators has finished.
for x in zip(1..4, 20..24):
  echo x
  Source
proc slice*[T](i: Iterable[T]; first = 0; last = 0; step = 1): iterator (): T
Yields every step item in i from index first to last.
for i in slice(0..100, 10, 20)
  echo i
  Source
proc delete*[T](i: Iterable[T]; first = 0; last = 0): iterator (): T
Yields the items in i except for the ones between first and last.
for x in delete(1..10, 4, 8):
  echo x
  Source
proc foldl*[T, S](i: Iterable[T]; f: proc (x: S; y: T): S; y: S): S

Folds the values as the iterator yields them, returning the accumulation.

As the initial value of the accumulation y is used.

echo foldl(1..10, proc(x,y: int): int = x + y, 0)
  Source
proc foldl*[T](i: Iterable[T]; f: proc (x, y: T): T): T

Folds the values as the iterator yields them, returning the accumulation.

The iterator is required to return at least a single element.

echo foldl(1..10, proc(x,y: int): int = x + y)
  Source

Iterators

iterator revItems*(a)
  Source
iterator revPairs*(a)
iterates over the items of a seq, array or string in reverse, yielding (index, a[index]).

var xs = @[1,3,5,7,9,11]

for i,x in xs.revPairs:
echo i, " ", x

  Source
iterator map*[T, S](i: Iterable[T]; f: proc (x: T): S): S
  Source
iterator filter*[T](i: Iterable[T]; f: proc (x: T): bool): T
  Source
iterator concat*[T](its: varargs[T, toIter]): auto
  Source
iterator zip*[T, S](i: (iterator (): T) | Slice[T]; j: Iterable[S]): tuple[a: T, 
    b: S]
  Source
iterator slice*[T](i: Iterable[T]; first = 0; last = 0; step = 1): T
  Source
iterator delete*[T](i: Iterable[T]; first = 0; last = 0): T
  Source