6.70. kink/iter/IFUN

Operations of ifuns.

“ifun” is an abbreviation of “iterator function.” An ifun is a fun which works as a pointer of a finite-length or infinite-length stream of values.

Usually, it is more convenient to use iters, which are wrappers of ifuns, rather than directly using ifuns. See kink/iter/ITER for iters.

Specification

An ifun is a 2ary fun, which takes $proc and $fin as arguments. The ifun must tail-call $proc if it has an element, or $fin if it has no element.

$proc is a 2ary fun, which takes `Head` and $tail as arguments. The ifun passes its first element as `Head`, and passes the next ifun, which points to remaining elements after `Head`, as $tail.

$fin is a thunk, which is tail-called when the ifun has no element.

Examples

In the next program, `make_vec_ifun` makes an ifun which iterates over the elements of `Vec`.

Let's make an `ifun`.

You can iterate over the elements of $nums_ifun using IFUN.each.

You can make another ifun mapping the elements.

You can accumulate the elements.

6.70.1. IFUN.each($ifun $consume)

`each` calls $consume for each element of $ifun.

Preconditions

$ifun must be an ifun.

$consume must be a function which takes an arg.

Example

6.70.2. IFUN.map($ifun $transform)

`map` returns an ifun whose nth element is transform(nth-element-of-$ifun).

Preconditions

$ifun must be an ifun.

$transform must take an arg.

Example

6.70.3. IFUN.concat_map($ifun $to_ifun)

`concat_map` returns an ifun which contains elements of ifuns which are results of to_ifun(element-of-$ifun).

Preconditions

$ifun must be an ifun.

$to_ifun must take an arg, and returns an ifun.

Example

6.70.4. IFUN.filter($ifun $include?)

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

Preconditions

$ifun must be an ifun.

$include? must be a predicate.

Example

6.70.5. IFUN.count($ifun $counted?)

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

The result is an int `num`.

Preconditions

$ifun must be an ifun.

$counted? must be a predicate.

Example

6.70.6. IFUN.fold($ifun Init $combine)

`fold` folds elements of $ifun seeded by `Init`.

If the elements of $ifun is E1, E2, ,,, En_1, En, `fold` returns combine(combine(,,,combine(combine(Init E1) E2),,, En_1) En).

If $ifun is empty, `fold` returns `Init`.

Preconditions

$ifun must be an ifun.

$combine must take two args.

Example

6.70.7. IFUN.reduce($ifun $combine ...[$empty_fallback])

`reduce` folds elements of $ifun mutually.

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

If $ifun has a single element `E`, `reduce` returns `E`.

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

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

Preconditions

$ifun must be an ifun.

$combine must take two args.

$empty_fallback must be a thunk.

Example

6.70.8. IFUN.take_front($ifun N)

`take_front` returns an ifun containing the first N elements of $ifun, or all the elements if $ifun has less than N elements.

Preconditions

$ifun must be an ifun.

`N` must be an int `num`.

Example

6.70.9. IFUN.drop_front($ifun N)

`drop_front` returns an ifun omitting the first N elements of $ifun, or an empty ifun if $ifun has less than N elements.

Preconditions

$ifun must be an ifun.

`N` must be an int `num`.

Example

6.70.10. IFUN.take_while($ifun $include?)

`take_while` returns an ifun of the longest initial prefix of $ifun, whose elements all satisfy $include?.

Preconditions

$ifun must be an ifun.

$include? must be a predicate.

Example

6.70.11. IFUN.drop_while($ifun $exclude?)

`drop_while` returns an ifun after the longest initial prefix of $ifun, whose elements all satisfy $exclude?.

Preconditions

$ifun must be an ifun.

$exclude? must be a predicate.

Example

6.70.12. IFUN.all?($ifun $match?)

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

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

Preconditions

$ifun must be an ifun.

$match? must be a predicate.

Example

6.70.13. IFUN.any?($ifun $match?)

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

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

Preconditions

$ifun must be an ifun.

$match? must be a predicate.

Example

6.70.14. IFUN.concat($ifun_of_ifuns)

`concat` returns an ifun which concatenates the ifuns contained in $ifun_of_ifuns.

Preconditions

$ifun_of_ifuns must be an ifun of ifuns.

Example

6.70.15. IFUN.unconcat($ifun Chunk_size)

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

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

Precondition

$ifun must be an ifun.

`Chunk_size` must be a positive int num.

Example

6.70.16. IFUN.cycle($ifun)

`cycle` returns an ifun which infinitely repeats the elements of $ifun.

If $ifun is empty, the result ifun will be also empty.

Precondition

$ifun must be an ifun.

Example

6.70.17. IFUN.of(...Elems)

`of` returns an ifun containing the elements of `Elems`.

Example

6.70.18. IFUN.join($front $back)

`join` makes an ifun concatenating two ifuns $front and $back.

The result ifun produces the elements of $front in the same order, and then the elements of $back in the same order.

Example

6.70.19. IFUN.zip($ifun ...Other_ifuns)

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

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

Preconditions

$ifun must be an ifun.

Each element of `Other_ifuns` must be an ifun.

Example

6.70.20. IFUN.lazy($make_ifun)

`lazy` returns an ifun, whose elements are equal to the ifun returned by $make_ifun.

$make_ifun is called when the result ifun is called.

Precondition

$make_ifun must be a thunk which returns an ifun.

Example

6.70.21. IFUN.from_generator($generator)

`from_generator` makes an ifun 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 ifun. When the invocation of $generator returns, it is the end of the ifun.

$generator is called when the result ifun is called. The invocation of $generator is suspended when $yield is called. The invocation is resumed when the trailing ifun is called.

Example: make a finite length ifun

Example: make an infinite length ifun

6.70.22. IFUN.from_each(Eacher)

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

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

Precondition

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

Example