# 3.51. kink/iter/IFUN¶

Provides operations for ifuns = iterator functions. An ifun represents the pointer to a specific position of a finite or infinite stream of elements.

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

The \$proc is a 2ary fun, which takes parameters Head and \$tail. The ifun passes its first element as an argument for Head, and passes the *next* ifun, which points to elements after Head, as an argument for \$tail.

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

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

```:make_vec_ifun <- {(:Vec)
{(:proc :fin)
Vec.nonempty?.if_else(
:tail = make_vec_ifun(Vec.drop_front(1))
}
{ fin }
)
}
}
```

Let's make an ifun using make_vec_ifun.

```:nums_ifun = make_vec_ifun([100 200 300])
```

For example, you can iterate over the elements of \$ifun_x using IFUN.each.

```IFUN.each(
\$nums_ifun
{(:N) dump(N) }
)
# Output:
#   100
#   200
#   300
```

Or you can make another ifun mapping the elements by a transforming fun.

```:doubled_ifun = IFUN.map(\$nums_ifun {(:N) N * 2 })
IFUN.each(
\$doubled_ifun
{(:N) dump(N) }
)
# Output:
#   200
#   400
#   600
```

Or you can accumulate the elements.

```:Sum = IFUN.fold(\$nums_ifun 0 {(:X :Y) X + Y })
dump(Sum) # => 600
```

## 3.51.1. IFUN.each(\$ifun \$on_elem)¶

Calls \$on_elem for each elements of \$ifun, then return the last result of \$on_elem.

If \$ifun has no elements, it returns nada.

## 3.51.2. IFUN.map(\$ifun \$transform)¶

Returns an ifun whose nth element is transform(nth-element-of-\$ifun).

## 3.51.3. IFUN.concat_map(\$ifun \$transform_to_ifun)¶

Returns an ifun which contains elements of ifuns which are results of transform_to_ifun(element-of-\$ifun).

## 3.51.4. IFUN.filter(\$ifun \$include?)¶

Filters elements of \$ifun by the predicate \$include?.

The result ifun only contains elements of \$ifun which satisfy \$include?. The order of elements are not changed.

## 3.51.5. IFUN.count(\$ifun \$counted?)¶

Returns the number of elements of \$ifun, which sattisfy \$counted?.

## 3.51.6. IFUN.fold(\$ifun Init \$combine)¶

Accumulates elements of \$ifun seeded by Init.

If the elements of \$ifun is E1, E2, ,,, En_1, En, this fun returns combine(combine(,,,combine(combine(Init E1) E2),,, En_1) En).

If \$ifun is empty, this fun returns Init.

## 3.51.7. IFUN.reduce(\$ifun \$combine)¶

Accumulates elements of \$ifun mutually, then returns a maybe list.

If \$ifun has elements E1, E2, E3, ,,, En_1, En, this fun returns [combine(combine(,,,combine(combine(E1 E2) E3),,, En_1) En)].

If \$ifun has a single element E, this fun returns [E].

If \$ifun is empty, this fun returns [].

## 3.51.8. IFUN.scan(\$ifun Init \$combine)¶

Returns an ifun of accumulated vals, seeded by Init.

If \$ifun points to finite n elements E(1), E(2), ,,, E(n), the result ifun points to finite n+1 elements R(0), R(1), R(2), ,,, R(n).

If \$ifun points to infinite elements E(1), E(2), ,,, , the result ifun points to infinite elements R(0), R(1), R(2), ,,, .

In both cases, R(i) is given as below:

For i=0, R(0) = Init.

For i>=1, R(i) = combine(R(i - 1) E(i)).

## 3.51.9. IFUN.scan_inside(\$ifun \$combine)¶

Returns an ifun of vals accumulated inside \$ifun.

If \$ifun points to no elements, the result ifun points to no elements.

If \$ifun points to finite n (n >= 1) elements E(1), E(2), ,,, E(n), the result ifun points to finite n elements R(1), R(2), ,,, R(n).

If \$ifun points to infinite elements E(1), E(2), ,,, , the result ifun points to infinite elements R(1), R(2), ,,, .

In the latter two cases, R(i) is given as below:

For i=1, R(1) = E(1).

For i>=2, R(i) = combine(R(i - 1) E(i)).

## 3.51.10. IFUN.take_front(\$ifun N)¶

Returns an ifun containing the first N elements of \$ifun, or all the elements if \$ifun has less than N elements.

## 3.51.11. IFUN.drop_front(\$ifun N)¶

Returns an ifun omitting the first N elements of \$ifun, or an empty ifun if \$ifun has less than N elements.

## 3.51.12. IFUN.take_while(\$ifun \$include?)¶

Returns an ifun of the longest initial prefix of \$ifun, whose elements all satisfy \$include?.

## 3.51.13. IFUN.drop_while(\$ifun \$exclude?)¶

Returns an ifun after the longest initial prefix of \$ifun, whose elements all satisfy \$exclude?.

## 3.51.14. IFUN.for_all?(\$ifun \$ok?)¶

Returns true if all the elements of \$ifun satisfy \$ok?. Returns false if at least one element of \$ifun does not satisfy \$ok?.

If \$ifun is infinite, this fun is not guaranteed to return.

## 3.51.15. IFUN.for_any?(\$ifun \$ok?)¶

Returns true if at least one element of \$ifun satisfies \$ok?. Returns false if all the elements of \$ifun does not satisfy \$ok?.

If \$ifun is infinite, this fun is not guaranteed to return.

## 3.51.16. IFUN.chunk(\$ifun Chunk_size)¶

Returns an ifun of chunks with the Chunk_size.

For example, if \$ifun contains E1, E2, E3, E4, E5, E6, E7, and Chunk_size is 2, this fun returns an ifun containing [E1 E2], [E3 E4] and [E5 E6]. The last E7 is ignored because there are not enough number of elements as a chunk.

Chunk_size must be an int num, and >= 1.

## 3.51.17. IFUN.concat(\$ifun_of_ifuns)¶

Returns an ifun which concatenates the ifuns contained in \$ifun_of_ifuns. \$ifun_of_ifuns should be an ifun whose elements are also ifuns.

## 3.51.18. IFUN.fetcher_thunk(\$ifun)¶

Makes a stateful thunk to fetch each element of the \$ifun.

When the result thunk is called, it returns a list containing the current element and go to next, when there are remaining elements. Otherwise, it returns an empty list.

For example:

```:ifun <- IFUN.of('foo' 'bar' 'baz')
:fetch <- IFUN.fetcher_thunk(\$ifun)
print_line(fetch.repr)  # => ["foo"]
print_line(fetch.repr)  # => ["bar"]
print_line(fetch.repr)  # => ["baz"]
print_line(fetch.repr)  # => []
print_line(fetch.repr)  # => []
```

## 3.51.19. IFUN.of(...Elems)¶

Returns an ifun containing the Elems.

## 3.51.20. IFUN.chain(\$xifun \$yifun)¶

Returns an ifun chaining \$xifun and \$yifun.

If \$xifun is finite and has elements X1, X2, ,,, Xn, and \$yifun has elements Y1, Y2, ,,, , the result ifun has X1, X2, ,,, Xn, Y1, Y2, ,,, .

If \$xifun is infinite, the result ifun has the same elements as ones of \$xifun.

## 3.51.21. IFUN.zip(\$ifun ...Other_ifuns)¶

Returns an ifun zpping the given ifuns.

For example, 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], ,,, .

The size of the result ifun is the minimum of the size of the arg ifuns.

## 3.51.22. IFUN.cycle(\$make_ifun)¶

Returns an ifun which concatenates elements of ifuns created by \$make_ifun thunk.

If \$make_ifun makes an empty ifun, the result ifun is terminated there.

## 3.51.23. IFUN.lazy(\$make_ifun)¶

Returns an ifun, whose elements are equal to the ifun returned by \$make_ifun.

## 3.51.24. IFUN.with_yield(\$body)¶

Makes an ifun of elements yielded in \$body.

\$body must take an unary fun \$yield as the arg, When \$yield is called with a vals in \$body, those vals will be the elements of the result ifun.

For example:

```:IFUN.require_from('kink/iter/')
:ifun = IFUN.with_yield{(:yield)
yield('foo')
yield('bar')
yield('baz')
}
IFUN.each(\$ifun){(:Str)
stdout.print_line(Str)
}
# Output:
#   foo
#   bar
#   baz
```

You can think that this fun provides an equivalent functionality to Python's generators.

## 3.51.25. IFUN.of_each(Eacher)¶

Makes an ifun of elements which is enumerated in Eacher.each.