- testing-status
- make-iterator
- is-iterator
- init
- to-iter
- cycle
- iterate
- nums
- repeatedly
- repeat
- prepend
- take
- drop
- rest
- reductions
- each
- map
- map-indexed
- keep
- filter
- remove
- interleave
- interpose
- unique
- take-while
- drop-while
- partition
- partition-all
- take-nth
- drop-last
- butlast
- keep-indexed
- blast
- first
- second
- nth
- some
- first-pred
- every
126 tests passed out of 126
100% of tests are passing
This module allows you to express infinite sequences. Typically you start by providing input to a generator, then pipe them into any number of iterators, and finally pipe that to a consumer.
Iterators have five zero-arity functions:
-
init: performs any initialization steps.
-
step: advances iteration to the next value.
-
curr: outputs the next value.
-
done: returns a boolean.
true
if the iterator has been exhusted
inf-iterator
& nest-iterator
are convenience wrappers around make-iterator
.
make-iterator
▶ [&curr=<closure 0xc0008a4900> &step=<closure 0xc0008a49c0> &done=<closure 0xc0008a4a80> &init=<closure 0xc0008a4840>]
make-iterator &init={ } &curr={ } &step={ } &done={ }
▶ [&curr=<closure 0xc000adc0c0> &step=<closure 0xc000adc180> &done=<closure 0xc000adc240> &init=<closure 0xc000adc000>]
Simple predicate for iterators. Runs done
to be sure it returns a bool.
All of the iterators satisfy this predicate.
range 10 | to-iter
▶ [&curr=<closure 0xc000862540> &step=<closure 0xc000862600> &done=<closure 0xc0008626c0> &init=<closure 0xc000862480>]
cycle a b c
▶ [&curr=<closure 0xc000a558c0> &step=<closure 0xc000a55980> &done=<closure 0xc000a55a40> &init=<closure 0xc000a55800>]
iterate $base:inc~ (num 0)
▶ [&curr=<closure 0xc000becb40> &step=<closure 0xc000becc00> &done=<closure 0xc000beccc0> &init=<closure 0xc000beca80>]
nums
▶ [&curr=<closure 0xc000b68240> &step=<closure 0xc000b68300> &done=<closure 0xc000b68600> &init=<closure 0xc000b68180>]
repeatedly { randint 100 }
▶ [&curr=<closure 0xc000b689c0> &step=<closure 0xc0008a4d80> &done=<closure 0xc000b68a80> &init=<closure 0xc0008a4c00>]
repeat (randint 100)
▶ [&curr=<closure 0xc000832480> &step=<closure 0xc0008a4d80> &done=<closure 0xc000832540> &init=<closure 0xc0008a4c00>]
to-iter d e f | prepend [a b c]
▶ [&curr=<closure 0xc000b69200> &step=<closure 0xc000b692c0> &done=<closure 0xc000b69440> &init=<closure 0xc000b69380>]
range 10 | to-iter | take 5
▶ [&curr=<closure 0xc000b452c0> &step=<closure 0xc000b45440> &done=<closure 0xc000b45a40> &init=<closure 0xc000b458c0>]
cycle a b c | reductions $base:append~ []
▶ [&curr=<closure 0xc000448cc0> &step=<closure 0xc000448fc0> &done=<closure 0xc000449380> &init=<closure 0xc000449080>]
use str; nums &start=(num 65) | each $str:from-codepoints~
▶ [&curr=<closure 0xc000448180> &step=<closure 0xc000448480> &done=<closure 0xc000449c80> &init=<closure 0xc0004495c0>]
nums | keep {|n| if (base:is-even $n) { put $n }}
▶ [&curr=<closure 0xc00056e840> &step=<closure 0xc00056e900> &done=<closure 0xc00056ea80> &init=<closure 0xc00056e9c0>]
nums | filter $base:is-even~
▶ [&curr=<closure 0xc000bd4f00> &step=<closure 0xc000bd5080> &done=<closure 0xc000bd5200> &init=<closure 0xc000bd5140>]
nums | remove $base:is-even~
▶ [&curr=<closure 0xc00056f8c0> &step=<closure 0xc00056f980> &done=<closure 0xc00056fb00> &init=<closure 0xc00056fa40>]
map $'+~' (to-iter (range 10)) (to-iter (range 10))
▶ [&curr=<closure 0xc0007fe600> &step=<closure 0xc0007fe840> &done=<closure 0xc0007feb40> &init=<closure 0xc0007fe3c0>]
nums &start=10 &step=10 | map-indexed $'*~'
▶ [&curr=<closure 0xc0000e1080> &step=<closure 0xc0000e1140> &done=<closure 0xc0000e1200> &init=<closure 0xc0000e0fc0>]
range 10 | to-iter | drop 5
▶ [&curr=<closure 0xc000a55500> &step=<closure 0xc000a555c0> &done=<closure 0xc000a55b00> &init=<closure 0xc000a55740>]
interleave (to-iter a b c) (to-iter 1 2 3)
▶ [&curr=<closure 0xc0008623c0> &step=<closure 0xc000862780> &done=<closure 0xc000862840> &init=<closure 0xc000862300>]
interpose , (range 10 | to-iter )
▶ [&curr=<closure 0xc000bec000> &step=<closure 0xc000bec0c0> &done=<closure 0xc000bec240> &init=<closure 0xc000bec180>]
unique (to-iter a b b c c c a a a a d)
▶ [&curr=<closure 0xc0000e1c80> &step=<closure 0xc0000e1d40> &done=<closure 0xc0000e1ec0> &init=<closure 0xc0000e1e00>]
unique (to-iter a b b c c c a a a a d) &count=$true
▶ [&curr=<closure 0xc000bed080> &step=<closure 0xc000bed140> &done=<closure 0xc000bed200> &init=<closure 0xc000becfc0>]
nums | take-while {|n| < $n 5}
▶ [&curr=<closure 0xc001199740> &step=<closure 0xc001199800> &done=<closure 0xc000aea240> &init=<closure 0xc001199a40>]
nums | drop-while {|n| < $n 5}
▶ [&curr=<closure 0xc000b45e00> &step=<closure 0xc000b45ec0> &done=<closure 0xc000263440> &init=<closure 0xc000263380>]
nums &stop=12 | partition 3
▶ [&curr=<closure 0xc000af8840> &step=<closure 0xc000af8a80> &done=<closure 0xc000af8b40> &init=<closure 0xc000af86c0>]
nums &stop=13 | partition-all 3
▶ [&curr=<closure 0xc000add080> &step=<closure 0xc000add140> &done=<closure 0xc000add200> &init=<closure 0xc000adcfc0>]
nums &stop=50 | take-nth 5
▶ [&curr=<closure 0xc000e85a40> &step=<closure 0xc000c8cf00> &done=<closure 0xc000c8db00> &init=<closure 0xc000c8da40>]
nums &stop=10 | drop-last 5
▶ [&curr=<closure 0xc000c8dec0> &step=<closure 0xc000bd4480> &done=<closure 0xc000bd4780> &init=<closure 0xc000bd4600>]
nums &stop=5 | butlast
▶ [&curr=<closure 0xc000739d40> &step=<closure 0xc0003aa6c0> &done=<closure 0xc0003aab40> &init=<closure 0xc0003aa780>]
to-iter a b c d e f g | keep-indexed {|i x| put [$i $x]} &pred=(fun:comp $base:first~ $base:is-odd~)
▶ [&curr=<closure 0xc000b13440> &step=<closure 0xc000b135c0> &done=<closure 0xc000b13bc0> &init=<closure 0xc000b138c0>]
The init function means that iterators should "start over" from the beginning.
var iter = (range 10 | to-iter)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (cycle a b c)
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (iterate $base:inc~ (num 0))
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums)
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (repeatedly { put x })
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (repeat (randint 100))
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (to-iter d e f | prepend [a b c])
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (range 10 | to-iter | take 5)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (cycle a b c | reductions $base:append~ [])
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
use str
var iter = (nums &start=(num 65) | each $str:from-codepoints~)
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums | keep {|n| if (base:is-even $n) { put $n }})
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums | filter $base:is-even~)
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums | remove $base:is-even~)
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (map $'+~' (to-iter (range 10)) (to-iter (range 10)))
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (nums &start=10 &step=10 | map-indexed $'*~')
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (range 10 | to-iter | drop 5)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (interleave (to-iter a b c) (to-iter 1 2 3))
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (interpose , (range 10 | to-iter ))
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (unique (to-iter a b b c c c a a a a d))
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (unique (to-iter a b b c c c a a a a d) &count=$true)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (nums | take-while {|n| < $n 5})
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums | drop-while {|n| < $n 5})
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums &stop=12 | partition 3)
eq (take 10 $iter | blast | fun:listify) (take 10 $iter | blast | fun:listify)
var iter = (nums &stop=13 | partition-all 3)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (nums &stop=50 | take-nth 5)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (nums &stop=10 | drop-last 5)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var iter = (nums &stop=5 | butlast)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
var pred = (fun:comp $base:first~ $base:is-odd~)
var iter = (to-iter a b c d e f g | keep-indexed {|i x| put [$i $x]} &pred=$pred)
eq (blast $iter | fun:listify) (blast $iter | fun:listify)
▶ $true
Simplest generator. Transforms an "array" to an iterator.
to-iter (range 10) | blast
range 10 | to-iter | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
cycles an "array" infinitely.
cycle a b c | take 10 | blast
put a b c | cycle | take 10 | blast
▶ a
▶ b
▶ c
▶ a
▶ b
▶ c
▶ a
▶ b
▶ c
▶ a
Returns an "array" of n, f(n), f(f(n)), etc.
iterate $base:inc~ (num 0) | take 10 | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
With no options, starts counting up from 0.
nums | take 10 | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
You can tell it to start at a specific value.
nums &start=10 | take 10 | blast
▶ 10
▶ 11
▶ 12
▶ 13
▶ 14
▶ 15
▶ 16
▶ 17
▶ 18
▶ 19
You can specify a step value.
nums &step=2 | take 5 | blast
▶ 0
▶ 2
▶ 4
▶ 6
▶ 8
It can be negative.
nums &step=-1 | take 10 | blast
▶ 0
▶ -1
▶ -2
▶ -3
▶ -4
▶ -5
▶ -6
▶ -7
▶ -8
▶ -9
Stop values can also be provided, although they offer little value over range
.
nums &stop=10 | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
nums
returns nothing if the inputs make no sense.
nums &step=-1 &stop=10 | blast
MATCHES EXPECTATIONS: [nothing]
Takes a zero-arity function and calls it infinitely.
repeatedly { randint 100 } | take 5 | blast
▶ 64
▶ 58
▶ 63
▶ 32
▶ 96
Returns x
infinitely
repeat x | take 5 | blast
▶ x
▶ x
▶ x
▶ x
▶ x
Prepends a list to an iterator
to-iter d e f | prepend [a b c] | blast
▶ a
▶ b
▶ c
▶ d
▶ e
▶ f
Like builtin:take
but for iterators.
cycle a b c | take 10 | blast
put a b c | cycle | take 10 | blast
▶ a
▶ b
▶ c
▶ a
▶ b
▶ c
▶ a
▶ b
▶ c
▶ a
Exceeding the length of a nested iterator is handled gracefully.
range 5 | to-iter | take 20 | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
Like builtin:drop
but for iterators.
range 10 | to-iter | drop 5 | blast
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
Dropping more than the nested iterator is handled gracefully.
range 10 | to-iter | drop 20 | blast
MATCHES EXPECTATIONS: [nothing]
Drops the first element from the iterator.
range 10 | to-iter | drop 5 | rest | blast
▶ 6
▶ 7
▶ 8
▶ 9
Like fun:reductions, but works with iterators.
cycle a b c | reductions $base:append~ [] | take 5 | blast
▶ []
▶ [a]
▶ [a b]
▶ [a b c]
▶ [a b c a]
Like builtin:each, but works with iterators
.
use str; nums &start=(num 65) | each $str:from-codepoints~ | take 3 | blast
▶ A
▶ B
▶ C
Like each
, but works with multiple iterators.
map $'+~' (to-iter (range 10)) (to-iter (range 10)) | take 5 | blast
▶ 0
▶ 2
▶ 4
▶ 6
▶ 8
Can work like each
, but you should avoid this because it is less performant.
use str; nums &start=(num 65) | map $str:from-codepoints~ | take 3 | blast
▶ A
▶ B
▶ C
Returns a sequence of (f index element)
.
nums &start=10 &step=10 | map-indexed $'*~' | take 5 | blast
▶ 0
▶ 20
▶ 60
▶ 120
▶ 200
Returns result of (f x)
when it's non-nil & non-empty.
Notice how these two results are different depending on where you place the take
.
nums | take 10 | keep {|n| if (base:is-even $n) { put $n }} | blast
▶ 0
▶ 2
▶ 4
▶ 6
▶ 8
nums | keep {|n| if (base:is-even $n) { put $n }} | take 10 | blast
▶ 0
▶ 2
▶ 4
▶ 6
▶ 8
▶ 10
▶ 12
▶ 14
▶ 16
▶ 18
Returns x
when (f x)
is non-empty & truthy.
nums | filter $base:is-even~ | take 5 | blast
▶ 0
▶ 2
▶ 4
▶ 6
▶ 8
Returns x
when (complement (f x))
is non-empty & truthy.
nums | remove $base:is-even~ | take 5 | blast
▶ 1
▶ 3
▶ 5
▶ 7
▶ 9
Returns a sequence of the first item in each iterator, then the second, etc.
interleave (to-iter a b c) (to-iter 1 2 3) | blast
▶ a
▶ 1
▶ b
▶ 2
▶ c
▶ 3
Understands when to stop short.
interleave (to-iter a b) (to-iter 1 2 3) | blast
interleave (to-iter a b c) (to-iter 1 2) | blast
▶ a
▶ 1
▶ b
▶ 2
Returns the elements from the nested iterator, interposed with sep
.
interpose , (to-iter a b c) | blast
▶ a
▶ ,
▶ b
▶ ,
▶ c
Needs to elements from iter in order to interpose sep.
interpose , (to-iter a) | blast
▶ a
Like uniq
but for iterators.
unique (to-iter a b b c c c a a a a) | blast
▶ a
▶ b
▶ c
▶ a
unique (to-iter a b b c c c a a a a d) | blast
▶ a
▶ b
▶ c
▶ a
▶ d
unique (to-iter a b b c c c a a a a) &count=$true | blast
▶ [a (num 1)]
▶ [b (num 2)]
▶ [c (num 3)]
▶ [a (num 4)]
unique (to-iter a b b c c c a a a a d) &count=$true | blast
▶ [a (num 1)]
▶ [b (num 2)]
▶ [c (num 3)]
▶ [a (num 4)]
▶ [d (num 1)]
Corner-case test
unique (to-iter a) | blast
▶ a
unique (to-iter a) &count=$true | blast
▶ [a (num 1)]
Returns elements so long as (f x)
returns $true.
nums | take-while {|n| < $n 5} | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
Drops elements until (f x)
returns false.
nums | drop-while {|n| < $n 5} | take 5 | blast
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
partitions an iterator into lists of size n.
nums &stop=12 | partition 3 | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 3) (num 4) (num 5)]
▶ [(num 6) (num 7) (num 8)]
▶ [(num 9) (num 10) (num 11)]
Drops items which don't complete the specified list size.
nums &stop=14 | partition 3 | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 3) (num 4) (num 5)]
▶ [(num 6) (num 7) (num 8)]
▶ [(num 9) (num 10) (num 11)]
Specify &step=n
to specify a "starting point" for each partition.
nums &stop=12 | partition 3 &step=5 | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 5) (num 6) (num 7)]
&step
can be < than the partition size.
nums &stop=4 | partition 2 &step=1 | blast
▶ [(num 0) (num 1)]
▶ [(num 1) (num 2)]
▶ [(num 2) (num 3)]
When there are not enough items to fill the last partition, a pad can be supplied.
nums &stop=14 | partition 3 &pad=[a] | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 3) (num 4) (num 5)]
▶ [(num 6) (num 7) (num 8)]
▶ [(num 9) (num 10) (num 11)]
▶ [(num 12) (num 13) a]
The size of the pad may exceed what is used.
nums &stop=13 | partition 3 &pad=[a b] | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 3) (num 4) (num 5)]
▶ [(num 6) (num 7) (num 8)]
▶ [(num 9) (num 10) (num 11)]
▶ [(num 12) a b]
...or not.
nums &stop=13 | partition 3 &pad=[] | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 3) (num 4) (num 5)]
▶ [(num 6) (num 7) (num 8)]
▶ [(num 9) (num 10) (num 11)]
▶ [(num 12)]
Convenience function for partition
which supplies &pad=[]
.
Use when you don't want everything in the resultset.
nums &stop=13 | partition-all 3 | blast
▶ [(num 0) (num 1) (num 2)]
▶ [(num 3) (num 4) (num 5)]
▶ [(num 6) (num 7) (num 8)]
▶ [(num 9) (num 10) (num 11)]
▶ [(num 12)]
Returns the nth element from the given iterator.
nums &stop=50 | take-nth 5 | blast
▶ 0
▶ 5
▶ 10
▶ 15
▶ 20
▶ 25
▶ 30
▶ 35
▶ 40
▶ 45
Drops the last n
elements from an iterator.
nums &stop=10 | drop-last 5 | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
Drops the last element from an iterator
nums &stop=5 | butlast | blast
▶ 0
▶ 1
▶ 2
▶ 3
Returns all non-empty & non-nil results of (f index item)
.
to-iter a b c d e f g | keep-indexed {|i x| if (base:is-odd $i) { put $x } else { put $nil }} | blast
▶ b
▶ d
▶ f
And supply your own predicate.
to-iter a b c d e f g | keep-indexed {|i x| put [$i $x]} &pred=(fun:comp $base:first~ $base:is-odd~) | blast
▶ [(num 1) b]
▶ [(num 3) d]
▶ [(num 5) f]
Simplest consumer. "Blasts" the iterator output to the terminal.
range 10 | to-iter | blast
▶ 0
▶ 1
▶ 2
▶ 3
▶ 4
▶ 5
▶ 6
▶ 7
▶ 8
▶ 9
Returns the first element from an iterator.
nums | first
▶ 0
Returns the second element from an iterator.
nums | second
▶ 1
Returns the nth element from an iterator
nums | nth 25
▶ 24
Returns the first truthy value from (f x)
.
nums &stop=20 | some {|i| < $i 50}
▶ $true
nums &stop=20 | some {|i| > $i 50}
▶ $false
nums &stop=20 | some {|i| if (< $i 50) { put $i } }
▶ 0
Might return nothing, if nothing fits.
nums &stop=20 | some {|i| if (> $i 50) { put $i } }
MATCHES EXPECTATIONS: [nothing]
Like filter but returns the first value.
nums &stop=20 | first-pred {|i| < $i 50}
▶ 0
nums | first-pred {|i| > $i 50}
▶ 51
nums &stop=20 | first-pred {|i| > $i 50}
MATCHES EXPECTATIONS: [nothing]
Returns $true
if every element satisfies the predicate. $false
otherwise.
nums &stop=20 | every {|i| < $i 50}
▶ $true
nums | every {|i| < $i 50}
▶ $false