3.58. 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)
if(! Vec.empty?
{ :Head = Vec.get(0)
:tail = make_vec_ifun(Vec.drop_front(1))
proc(Head $tail)
}
{ 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
- IFUN.each($ifun $on_elem)
- IFUN.map($ifun $transform)
- IFUN.concat_map($ifun $transform_to_ifun)
- IFUN.filter($ifun $include?)
- IFUN.count($ifun $counted?)
- IFUN.fold($ifun Init $combine)
- IFUN.reduce($ifun $combine)
- IFUN.scan($ifun Init $combine)
- IFUN.scan_inside($ifun $combine)
- IFUN.take_front($ifun N)
- IFUN.drop_front($ifun N)
- IFUN.take_while($ifun $include?)
- IFUN.drop_while($ifun $exclude?)
- IFUN.for_all?($ifun $ok?)
- IFUN.for_any?($ifun $ok?)
- IFUN.chunk($ifun Chunk_size)
- IFUN.concat($ifun_of_ifuns)
- IFUN.fetcher_thunk($ifun)
- IFUN.of(...Elems)
- IFUN.chain($xifun $yifun)
- IFUN.zip($ifun ...Other_ifuns)
- IFUN.cycle($make_ifun)
- IFUN.lazy($make_ifun)
- IFUN.with_yield($body)
- IFUN.of_each(Eacher)
3.58.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.58.2. IFUN.map($ifun $transform)¶
Returns an ifun whose nth element is transform(nth-element-of-$ifun).
3.58.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.58.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.58.5. IFUN.count($ifun $counted?)¶
Returns the number of elements of $ifun, which sattisfy $counted?.
3.58.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.58.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.58.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.58.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.58.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.58.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.58.12. IFUN.take_while($ifun $include?)¶
Returns an ifun of the longest initial prefix of $ifun, whose elements all satisfy $include?.
3.58.13. IFUN.drop_while($ifun $exclude?)¶
Returns an ifun after the longest initial prefix of $ifun, whose elements all satisfy $exclude?.
3.58.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.58.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.58.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.58.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.58.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.58.19. IFUN.of(...Elems)¶
Returns an ifun containing the Elems.
3.58.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.58.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.58.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.58.23. IFUN.lazy($make_ifun)¶
Returns an ifun, whose elements are equal to the ifun returned by $make_ifun.
3.58.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.58.25. IFUN.of_each(Eacher)¶
Makes an ifun of elements which is enumerated in Eacher.each.