6.64. kink/iter/ITER

6.64.1. type iter

“iter” is an abbreviation of “iterator.” An `iter` is a finite-length or infinite-length stream of values.

An `iter` is just a wrapper of an ifun. See kink/iter/IFUN for ifuns.

6.64.1.1. Iter.ifun

`ifun` returns the ifun wrapped by `Iter`.

Example

:IFUN.require_from('kink/iter/')

:Num_iter <- 5.times

Num_iter.each{(:N) stdout.print_line(N.repr) }
# => 0 1 2 3 4

:nums <- Num_iter.ifun
IFUN.each($nums){(:N) stdout.print_line(N.repr) }
# => 0 1 2 3 4

6.64.1.2. Iter.each($consume)

`each` calls $consume for each element of `Iter`, then returns the last result of $consume.

If `Iter` has no elements, `each` returns nada.

Precondition

$consume must be a fun which takes an arg.

Example

3.times.each{(:E)
  stdout.print_line(E.repr)
}
# Output:
#   0
#   1
#   2

6.64.1.3. Iter.map($transform)

`map` returns an `iter` whose nth element is transform(nth-element-of-Iter).

Precondition

$transform must take an arg.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4)
:Doubles <- Ns.map{(:N) N * 2 }
Doubles.each{(:D)
  stdout.print_line(D.repr)
}
# Output:
#   2
#   4
#   6
#   8

6.64.1.4. Iter.concat_map($to_iter)

`concat_map` returns an `iter` which concatenates iters which are results of to_iter(element-of-Iter).

Precondition

$to_iter must take an arg, and returns an `iter`.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4)
:Mapped <- Ns.concat_map{(:N)
  N.times
}
Mapped.each{(:M) stdout.print_line(M.repr) }
# => 0 0 1 0 1 2 0 1 2 3

6.64.1.5. Iter.filter($include?)

`filter` returns all the elements of `Iter` which satisfy $include?, as an `iter`. The order of elements is not changed.

Precondition

$include? must be a predicate.

Example

:ITER.require_from('kink/iter/')

:Orig <- ITER.of(1 2 3 4 5 6 7 8 9)
:Evens <- Orig.filter{(:N) N % 2 == 0 }
Evens.each{(:N)
  stdout.print_line(N.repr)
}
# Output:
#   2
#   4
#   6
#   8

6.64.1.6. Iter.count($counted?)

`count` returns the number of elements of `Iter`, which satisfy $counted?.

The result is an int `num`.

Preconditions

$counted? must be a predicate.

Example

:ITER.require_from('kink/iter/')

:Nums <- ITER.of(1 2 3 4 5 6 7 8 9)
:Count <- Nums.count{(:N) N % 2 == 0 }
stdout.print_line(Count.repr) # => 4

6.64.1.7. Iter.fold(Init $combine)

`fold` folds elements of `Iter` seeded by `Init`.

If the elements of `Iter` are E1, E2, ,,, En_1, En, `fold` returns combine(combine(,,,combine(combine(Init E1) E2),,, En_1) En).

If `Iter` is empty, `fold` returns `Init`.

Precondition

$combine must takes two args.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.fold(100){(:X :Y) X + Y }.repr)  # => 115

6.64.1.8. Iter.reduce($combine ...[$empty_fallback])

`reduce` folds elements of `Iter` mutually.

If `Iter` has elements E1, E2, E3, ,,, En_1, En, `reduce` returns combine(combine(,,,combine(combine(E1 E2) E3),,, En_1) En).

If `Iter` has a single element `E`, `reduce` returns `E`.

If `Iter` has no element, and $empty_fallback is given, `reduce` tail-calls $empty_fallback with no arg.

If `Iter` has no element, and $empty_fallback is not given, `reduce` raises an exception.

Preconditions

$combine must take two args.

$empty_fallback must be a thunk.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.reduce{(:X :Y) X + Y }.repr)  # => 15

6.64.1.9. Iter.take_front(N)

take_front returns the first N elements of `Iter` as an `iter`. If `Iter` has less than N elements, take_front returns an `iter` which has all the elements of `Iter`.

Preconditions

N must be an int `num`.

Example

:ITER.require_from('kink/iter/')

1.up.take_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 4 5

ITER.of(1 2 3).take_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3

6.64.1.10. Iter.drop_front(N)

drop_front returns elements of `Iter` excluding the first N elements, as an `iter`. If `Iter` has less than N elements, drop_front returns an empty `iter`.

Preconditions

N must be an int `num`.

Example

:ITER.require_from('kink/iter/')

10.times.drop_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 5 6 7 8 9

10.times.drop_front(20).each{(:N)
  stdout.print_line(N.repr)
}
# Output: nothing

6.64.1.11. Iter.take_while($include?)

take_while returns the longest prefix of `Iter`, whose elements all satisfy $include?, as an `iter`.

Preconditions

$include? must be a predicate.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1000 500 250 125 62 31 15 7 3 1 0)
:Front <- Ns.take_while{(:N) N % 2 == 0 }
Front.each{(:N) stdout.print_line(N.repr) }
# => 1000 500 250

6.64.1.12. Iter.drop_while($exclude?)

drop_while excludes the longest prefix of `Iter` whose elements all satisfy $exclude?, and returns the rest as an `iter`.

Preconditions

$exclude? must be a predicate.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1000 500 250 125 62 31 15 7 3 1 0)
:Back <- Ns.drop_while{(:N) N % 2 == 0 }
Back.each{(:N) stdout.print_line(N.repr) }
# => 125 62 31 15 7 3 1 0

6.64.1.13. Iter.all?($match?)

`all?` returns true if all the elements of `Iter` satisfy $match?, otherwise returns false.

If `Iter` is infinite-length, `all?` is not guaranteed to return.

Preconditions

$match? must be a predicate.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.all?{(:N) N < 10 }.repr)      # => true
stdout.print_line(Ns.all?{(:N) N % 2 == 0 }.repr)  # => false

6.64.1.14. Iter.any?(...[$match?={ true }])

`any?` returns true if one or more elements of `Iter` satisfy $match?, otherwise returns false.

If `Iter` is infinite-length, `any?` is not guaranteed to return.

The default value of $match? is { true }. So, if $match? is not passed, `any?` returns whether `Iter` is nonempty.

Preconditions

$match? must be a predicate.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5)
stdout.print_line(Ns.any?{(:N) N % 2 == 0 }.repr)  # => true
stdout.print_line(Ns.any?{(:N) N > 10 }.repr)      # => false

Example

:ITER.require_from('kink/iter/')

stdout.print_line(ITER.of().any?.repr)    # => false
stdout.print_line(ITER.of(1).any?.repr)   # => true
stdout.print_line(ITER.of(1 2).any?.repr) # => true

6.64.1.15. Iter.concat

`concat` returns an iter, which concatenates the elements of iters in `Iter`.

Precondition

`Iter` must be an `iter` of iters.

Example

:ITER.require_from('kink/iter/')

:Nums <- ITER.of(1 2 3)
:Strs <- ITER.of('foo' 'bar')
:Bools <- ITER.of(true false)
ITER.of(Nums Strs Bools).concat.each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 "foo" "bar" true false

6.64.1.16. Iter.unconcat(Chunk_size)

`unconcat` splits `Iter` into vecs whose size is `Chunk_size`, and returns an `iter` of those vecs.

If the size of `Iter` is a finite number Chunk_size * N + R, where N and R are non-negative integers, the last R elements of `Iter` will be discarded.

Precondition

`Chunk_size` must be a positive int num.

Example

:ITER.require_from('kink/iter/')

:Ns <- ITER.of(1 2 3 4 5 6 7)
:Chunks <- Ns.unconcat(2)
Chunks.each{(:Chunk)
  stdout.print_line(Chunk.repr)
}
# Output:
#   [1 2]
#   [3 4]
#   [5 6]

6.64.1.17. Iter.cycle

`cycle` returns an `iter` which infinitely repeats the elements of `Iter`.

If `Iter` is empty, the result `iter` will be also empty.

Example

:ITER.require_from('kink/iter/')

3.times.cycle.take_front(10).each{(:N)
  stdout.print_line(N.repr)
}
# => 0 1 2 0 1 2 0 1 2 0

ITER.of().cycle.each{(:N)
  stdout.print_line(N.repr)
}
# Output: nothing

6.64.1.18. Front + Back

`+` operator, or `op_add` method, concatenates two iters `Front` and `Back` into a single `iter`.

Precondition

`Front` and `Back` must be `iter` vals.

Example

:Iter <- 1.up.take_front(3) + 11.up.take_front(3)
Iter.each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 11 12 13

6.64.2. ITER.new($ifun)

`new` makes an `iter` wrapping $ifun.

Precondition

$ifun must be an ifun.

Example

:ITER.require_from('kink/iter/')

:make_vec_ifun <- {(:Vec)
  {(:proc :fin)
    if(Vec.any?
      { :Head = Vec.get(0)
        :tail = make_vec_ifun(Vec.drop_front(1))
        proc(Head $tail)
      }
      { fin }
    )
  }
}
:Iter <- ITER.new(make_vec_ifun(['foo' 'bar' 'baz']))
Iter.each{(:S)
  stdout.print_line(S)
}
# Output:
#   foo
#   bar
#   baz

6.64.3. ITER.is?(Val)

`is?` returns whether `Val` is an `iter`.

6.64.4. ITER.of(...Elems)

`of` returns an `iter` containing `Elems`.

Example

:ITER.require_from('kink/iter/')

:Iter <- ITER.of('foo' 'bar' 'baz')
Iter.each{(:S)
  stdout.print_line(S)
}
# Output:
#   foo
#   bar
#   baz

6.64.5. ITER.zip(First_iter ...Other_iters)

If `zip` is passed N iters, `zip` returns an `iter` as long as the shortest of these iters, each element of which is an N-element vec comprised of the corresponding elements from the passed iters.

For example, if an iter X has elements X1, X2, X3, ,,, , an iter Y has elements Y1, Y2, Y3, ,,, , and an iter Z has elements Z1, Z2, Z3, ,,, , zip(X Y Z) returns an iter containing [X1 Y1 Z1], [X2 Y2 Z2], [X3 Y3 Z3], ,,, .

Preconditions

Each element of `Other_iters` must be an `iter`.

Example

:ITER.require_from('kink/iter/')

:Zipped <- ITER.zip(
  ITER.of(1 2 3 4 5)
  ITER.of('foo' 'bar' 'baz')
  ITER.of(true false true)
)
Zipped.each{(:Triple)
  stdout.print_line(Triple.repr)
}
# Output:
#   [1 "foo" true]
#   [2 "bar" false]
#   [3 "baz" true]

6.64.6. ITER.lazy($make_iter)

`lazy` makes an `iter` which delegates production of the elements to an `iter` returned by $make_iter.

The thunk $make_iter is called when the contents of the result `iter` is needed.

Precondition

$make_iter must be a thunk which returns an `iter`.

Example

:ITER.require_from('kink/iter/')

:count_down <- {(:N)
  if(N < 0
    { ITER.of() }
    { ITER.of(N) + ITER.lazy{ count_down(N - 1) } }
  )
}
count_down(5).each{(:N)
  stdout.print_line(N.repr)
}
# => 5 4 3 2 1 0

6.64.7. ITER.from_generator($generator)

`from_generator` makes an `iter` of elements yielded in $generator.

$generator must take an unary fun $yield as the arg, When $yield is called with a val in invocation of $generator, that val will be an element of the result `iter`. When the invocation of $generator returns, it is the end of the `iter`.

$generator is called when the contents of the result `iter` is needed. The invocation of $generator is suspended when $yield is called. The invocation is resumed when the contents of the trailing `iter` is needed.

Example: make a finite length iter

:ITER.require_from('kink/iter/')

:Iter <- ITER.from_generator{(:yield)
  yield('foo')
  yield('bar')
  yield('baz')
}
Iter.each{(:Str)
  stdout.print_line(Str)
}
# Output:
#   foo
#   bar
#   baz

Example: make an infinite length iter

:ITER.require_from('kink/iter/')

:Iter <- ITER.from_generator{(:yield)
  :loop <- {(:N)
    yield(N)
    loop(N + 1)
  }
  loop(1)
}
Iter.take_front(5).each{(:N)
  stdout.print_line(N.repr)
}
# Output:
#   1
#   2
#   3
#   4
#   5

6.64.8. ITER.from_each(Eacher)

`from_each` makes an `iter` of values which are enumerated in Eacher.each.

The invocation of `each` is suspended and resumed for evaluation of each element of the `iter`.

Precondition

`Eacher` must support each($consume) method, which is called to enumerate each element of `Eacher`.

Example

:ITER.require_from('kink/iter/')

:Take_five <- ITER.from_each([1 2 3 4 5])
Take_five.each{(:N)
  stdout.print_line(N.repr)
}
# => 1 2 3 4 5