1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
## std.iterators: The Iter class and associated functions.
## This module is imported by default.
# reference: https://doc.rust-lang.org/std/iter/
# reference: https://docs.rs/itertools/latest/itertools/
use std.queue.ring
## The Iter class. Any type implementing `next()` is iterable.
pub type Iter[T] = class
next(mut Self): T? # should T be lent?
## The IntoIter class.
## Any type implementing `iter()` may be converted to an iterable type.
pub type IntoIter[T] = class
iter(Self): Iter[T]
## The Peek class.
## Any type implementing `Iter`, `peek`, and `peek_nth` is peekable.
pub type Peek[T] = class
next(mut Self): T?
peek(mut Self): T?
peek_nth(mut Self, int): T?
## A concrete Peekable structure formed from a generic Iter type.
## Implements the Peek class. Can be formed with `.peekable()`
type PeekImpl = struct
iter: ref Iter[T] # this is probably bad... heap allocated...
buf: Queue[T]
## Convert any Iter into a peekable equivalent.
# https://github.com/LukeMathWalker/multipeek/blob/main/src/lib.rs
pub func peekable[T](iter: owned Iter[T]): PeekImpl[T] =
{ iter, buf: ... } # todo: implement Queue, somewhere
pub func next[T](self: mut PeekImpl[T]): T? =
match self.buf.pop()
of None then
self.iter.next()
of Some(val) then
val
pub func peek[T](self: mut PeekImpl[T]): T? =
match self.buf.peek()
of None then
self.buf.push(self.iter.next())
self.buf.peek()
of Some(val) then
val
pub func peek_nth[T](self: mut PeekImpl[T], i: uint): T? =
if self.buf.len > i then
self.buf.get(i)!
else
for _ in self.buf.len .. i do # fixme
match self.buf.next()
of None then
return None
of Some(val) then
self.buf.push(val)
self.buf.peek()
# todo: useful functions for an iterator
# https://doc.rust-lang.org/std/iter/trait.Iterator.html#provided-methods
func advance_by[T](self: Iter[T], n: uint) =
for i in 0 .. n do
if self.next().is_none() then return
pub func get[T](self: Iter[T], at: uint): T?
self.advance_by(at-1).ok? # fixme
self.next()
## Returns true if every element in an Iter fulfills the conditional.
pub func all[T](self: Iter[T], cond: T -> bool): bool =
for elem in self do
if not cond(elem) then return false
true
## Returns true if any element in an Iter fulfills the conditional.
pub func any[T](self: Iter[T], cond: T -> bool): bool =
for elem in self do
if cond(elem) then return true
false
## Returns true if an Iter contains the given element.
pub func contains[T](self: Iter[T], val: T): bool =
self.any(elem => elem == val)
## Returns the first element matching a condition, if it exists.
pub func find[T](self: Iter[T], cond: T -> bool): T? =
for elem in self do
if cond(elem) then return Some(elem)
None
## Returns the position of the first element matching a condition, if it exists.
pub func position[T](self: Iter[T], cond: T -> bool): T? =
var i = 0
for elem in self do
if cond(elem) then return Some(i)
i += 1
None
@[inline]
pub func fold[T, U](self: Iter[T], init: U, op: (U, T) -> U) =
var res = init
for elem in self do
res = res.op(elem)
res
pub func reduce[T, U](self: Iter[T], op: (U, T) -> U): U? =
match self.next()
of None then None
of Some(val) then
var res = val
for elem in self do res = op(res, elem)
Some(res)
pub func count[T](self: Iter[T], element: T): uint =
self.fold(0, (elem, acc) => if elem == element then acc + 1 else acc)
pub func count[T](self: Iter[T]): uint =
self.fold(0, (elem, acc) => acc + 1)
pub func last[T](self: Iter[T]): T =
var res = None
for elem in self do res = elem
res
pub func ==[T](first: Iter[T], second: Iter[T]): bool =
if first.len != second.len then return false
for (a, b) in zip(first, second) do
if a != b then return false
true
type LazyIter = struct
...
pub func apply[T](self: mut LazyIter[T], fn: T -> T)
pub func map[T, S](self: Iter[T], fn: T -> S): LazyIter[S]
pub func foreach[T, S](self: Iter[T], fn: T -> S): LazyIter[T]
pub func enumerate[T](self: LazyIter[T]): LazyIter[T] # todo: impl with map or similar
pub func dedup[T](self: Iter[T], sorted = false): LazyIter[T]
pub func filter[T](self: Iter[T], cond: T -> bool): LazyIter[T]
## Takes (at most) the first `n` elements of an iterator.
pub func take[T](self: Iter[T], n: uint): LazyIter[T]
## Skips (at most) the first `n` elements of an iterator.
pub func skip[T](self: Iter[T], n: uint): LazyIter[T]
pub func repeat[T](self: Iter[T], n: uint): LazyIter[T] # cycle??
pub func intersperse[T](self: Iter[T], item: T): LazyIter[T]
pub func step[T](self: Iter[T], step: uint): LazyIter[T]
pub func flatten[T](self: Iter[Iter[T]]): LazyIter[T]
pub func chain[T](first: Iter[T], second: Iter[T]): LazyIter[T]
pub func zip[T, U](first: Iter[T], second: Iter[U]): Iter[(T, U)]
pub func unzip[T, U](self: Iter[(T, U)]): (Iter[T], Iter[U])
# equivalent of collect. useful for type conversion
pub func to[T](self: LazyIter[T]): list[T]
pub func to(self: LazyIter[chr]): str
pub type BoundIter[T] = class
next(mut Self): T?
pop(mut Self): T?
pub func rev[T](self: BoundIter[T]): BoundIter[T]
pub type SizedIter[T] = class
next(mut Self): T?
pop(mut Self): T?
len(Self): uint
get(mut Self): T?
pub func max(self: Iter[Comparable[T]]): T
pub func min(self: Iter[Comparable[T]]): T
pub func sorted(self: Iter[Comparable[T]]): bool
|