## 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