aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/iterators.pk
diff options
context:
space:
mode:
Diffstat (limited to 'std/prelude/iterators.pk')
-rw-r--r--std/prelude/iterators.pk187
1 files changed, 167 insertions, 20 deletions
diff --git a/std/prelude/iterators.pk b/std/prelude/iterators.pk
index 224460f..82137ee 100644
--- a/std/prelude/iterators.pk
+++ b/std/prelude/iterators.pk
@@ -1,38 +1,185 @@
## std.iterators: The Iter interface 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 interface. Any type implementing `next()` is iterable.
pub type Iter[T] = interface
- next(mut Self): Option[T]
+ next(mut Self): T? # should T be lent?
+
+## The IntoIter interface.
+## Any type implementing `iter()` may be converted to an iterable type.
+pub type IntoIter[T] = interface
+ iter(Self): Iter[T]
+
+## The Peek interface.
+## Any type implementing `Iter`, `peek`, and `peek_nth` is peekable.
+pub type Peek[T] = interface
+ 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 interface. 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:
+ self.iter.next()
+ of Some(val):
+ val
+pub func peek[T](self: mut PeekImpl[T]): T? =
+ match self.buf.peek()
+ of None:
+ self.buf.push(self.iter.next())
+ self.buf.peek()
+ of Some(val):
+ val
+pub func peek_nth[T](self: mut PeekImpl[T], i: uint): T? =
+ if self.buf.len > i:
+ self.buf.get(i)!
+ else:
+ for _ in self.buf.len .. i: # fixme
+ match self.buf.next()
+ of None:
+ return None
+ of Some(val):
+ 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
-pub func advance_by[T](self: Iter[T], n: uint): Result[T, ...] =
+func advance_by[T](self: Iter[T], n: uint) =
for i in 0 .. n:
if self.next().is_none():
- return Error(...)
- Okay
+ return
pub func get[T](self: Iter[T], at: uint): Option[T]
- self.advance_by(at-1).ok?
+ self.advance_by(at-1).ok? # fixme
self.next()
-# todo: implement iter[T](self: ...): Iter[T] funcs
-# todo: efficient functional methods
+## 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:
+ if not cond(elem):
+ return false
+ true
-## The Peek interface. Any type implementing `Iter`, `peek`, and `peek_nth` is peekable.
-pub type Peek[T] = interface
- next(mut Self): Option[T]
- peek(mut Self): Option[T]
- peek_nth(mut Self, int): Option[T]
+## 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:
+ if cond(elem):
+ return true
+ false
-# todo: implement peek[T](self: Iter[T]): Peek[T]
-# todo: implement Peekable struct
-# https://github.com/LukeMathWalker/multipeek/blob/main/src/lib.rs
+## 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:
+ if cond(elem):
+ 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:
+ if cond(elem):
+ return Some(i)
+ i += 1
+ None
+
+pub func fold[T, U](self: Iter[T], init: U, op: (U, T) -> U) =
+ var res = init
+ for elem in self:
+ res = res.op(elem)
+ res
+
+pub func reduce[T, U](self: Iter[T], op: (U, T) -> U): U? =
+ match self.next()
+ of None:
+ None
+ of Some(val):
+ var res = val
+ for elem in self:
+ res = op(res, elem)
+ Some(res)
+
+pub func count[T](self: Iter[T], element: T): uint =
+ self.fold(0, (elem, acc) => if elem == element: 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:
+ res = elem
+ res
+
+pub func ==[T](first: Iter[T], second: Iter[T]): bool =
+ for (a, b) in :
+ if a != b:
+ 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 from[T](self: LazyIter[T]): list[T]
+pub func from(self: LazyIter[chr]): str
+
+pub type BoundIter[T] = interface
+ next(mut Self): T?
+ pop(mut Self): T?
+
+pub func rev[T](self: BoundIter[T]): BoundIter[T]
+
+pub type SizedIter[T] = interface
+ next(mut Self): T?
+ pop(mut Self): T?
+ len(Self): uint
+ get(mut Self): T?
-## We don't want a Countable. It's not terribly useful.
-# pub type Countable[T] = interface
-# next(mut Self): Option[T]
-# len(Self): uint
-# get(Self, uint): Option[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