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