package dotty1.collections
package immutable
import annotation.unchecked.uncheckedVariance
object Iter2 {
trait Iterator[+A] extends IterableOnce[A] {
def hasNext: Boolean
def next: A
def iterator = this
def foreach(f: A => Unit): Unit = ???
def map[B](f: A => B): Iterator[B] = ???
def flatMap[B](f: A => IterableOnce[B]): Iterator[B] = ???
def ++[B >: A](xs: IterableOnce[B]): Iterator[B] = ???
def drop(n: Int): Iterator[A] = ???
def indexWhere(p: A => Boolean): Int = {
var i = 0
while (hasNext) {
if (p(next)) return i
i += 1
}
-1
}
def zip[B](that: Iterator[B]): Iterator[(A, B)] = ???
def copy: Iterator[A] = ???
}
/*
trait View[+A] { self =>
def iterator: Iterator[A]
def foreach(f: A => Unit): Unit = iterator.foreach(f)
def map[B](f: A => B): View[B] =
new View[B] { def iterator = self.iterator.map(f) }
def flatMap[B](f: A => IterableOnce[B]): View[B] =
new View[B] { def iterator = self.iterator.flatMap(f) }
def ++[B >: A](xs: IterableOnce[B]): View[B] =
new View[B] { def iteratpr = self.iterator ++ xs }
def drop(n: Int): View[A] =
new View[A] { def iteratpr = self.iterator.drop(n) }
def indexWhere(p: A => Boolean): Int = {
var i = 0
while (hasNext) {
if (p(next)) return i
i += 1
}
-1
}
def zip[B](that: Iterator[B]): Iterator[(A, B)] = ???
}
*/
trait IterableOnce[+A] {
def iterator: Iterator[A]
def buildIterator: Iterator[A] = iterator
}
trait FromIterator[+C[X] <: Iterable[X]] {
def fromIterator[B](it: Iterator[B]): C[B]
}
trait Iterable[+IA] extends IterableOnce[IA] with FromIterator[Iterable] {
def view: View[IA] = new View(iterator)
}
trait Seq[+AA] extends Iterable[AA] with FromIterator[Seq] {
def apply(i: Int): AA
def length: Int
}
sealed trait List[+A] extends Seq[A] with FromIterator[List] {
def isEmpty: Boolean
def head: A
def tail: List[A]
def iterator = new ListIterator[A](this)
def fromIterator[B](it: Iterator[B]): List[B] = it match {
case ListIterator(xs) => xs
case _ => if (it.hasNext) Cons(it.next, fromIterator(it)) else Nil
}
def apply(i: Int): A = {
require(!isEmpty)
if (i == 0) head else tail.apply(i - 1)
}
def length: Int =
if (isEmpty) 0 else 1 + tail.length
}
class View[+A](it: Iterator[A]) extends Iterable[A] with FromIterator[View] {
def iterator: Iterator[A] = it.copy
def fromIterator[B](it: Iterator[B]): View[B] = new View(it)
}
case class Cons[+A](x: A, xs: List[A]) extends List[A] {
def isEmpty = false
def head = x
def tail = xs
}
case object Nil extends List[Nothing] {
def isEmpty = true
def head = ???
def tail = ???
}
class ArrayBuffer[A] private (initElems: Array[AnyRef], initLen: Int) extends Seq[A] with FromIterator[ArrayBuffer] {
def this() = this(new Array[AnyRef](16), 0)
def this(it: ArrayIterator[A]) = this(it.elems, it.len)
private var elems: Array[AnyRef] = initElems
private var len = 0
def iterator =
elems.iterator.take(len).asInstanceOf[Iterator[A]]
override def buildIterator =
new ArrayIterator(elems, len).asInstanceOf[Iterator[A]]
def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] =
new ArrayBuffer(ArrayIterator.fromIterator(it))
def apply(i: Int) = elems(i).asInstanceOf[A]
def length = len
}
/*
class SeqView[A](itf: () => Iterator) extends Seq[A] with FromIterator[SeqView] {
def iterator = it
def buildIterator = it
def fromIterator[B](it: Iterator[B]) = it match {
case ViewIterator(itf) => SeqView(itf)
}
}
*/
implicit class IterableTransforms[A, C[X] <: Iterable[X]](val c: Iterable[A] with FromIterator[C]) extends AnyVal {
def map[B](f: A => B): C[B] = c.fromIterator(c.buildIterator.map(f))
def flatMap[B](f: A => IterableOnce[B]): C[B] = c.fromIterator(c.buildIterator.flatMap(f(_).buildIterator))
def ++[B >: A](xs: IterableOnce[B]): C[B] = c.fromIterator(c.buildIterator ++ xs.buildIterator)
def drop(n: Int): C[A] = c.fromIterator(c.buildIterator.drop(n))
def head: A = c.iterator.next
def zip[B](xs: IterableOnce[B]): C[(A, B)] = c.fromIterator(c.iterator.zip(xs.iterator))
}
implicit class SeqTransforms[SA, C[X] <: Seq[X]](val c: Seq[SA] with FromIterator[C]) extends AnyVal {
def reverse: C[SA] = {
val elems = new Array[AnyRef](c.length)
var i = elems.length
val it = c.iterator
while (it.hasNext) {
i -= 1
elems(i) = it.next.asInstanceOf[AnyRef]
}
val xzz = c.fromIterator(ArrayIterator[SA](elems, c.length))
xzz
}
def indexWhere(p: SA => Boolean): Int = c.iterator.indexWhere(p)
}
/*
case class ViewIterator[+A](itf: () => Iterator) extends Iterator[A] {
def hasNext = it.hasNext
def next
def map(f: A => B): ViewIterator[B] = ViewIterator(() => it().map(f))
def
}
*/
case class ListIterator[+A](xs: List[A]) extends Iterator[A] {
private[this] var current: List[A] = xs
def hasNext = !current.isEmpty
def next = { val res = current.head; current = current.tail; res }
}
case class ArrayIterator[+A](elems: Array[AnyRef], len: Int) extends Iterator[A] {
import ArrayIterator._
private def elem(i: Int) = elems(i).asInstanceOf[A]
private var cur = 0
def hasNext = cur < len
def next = { val res = elem(cur); cur += 1; res }
override def foreach(f: A => Unit): Unit =
for (i <- 0 until len) f(elem(i))
override def map[B](f: A => B): ArrayIterator[B] = {
var mapped = elems
for (i <- 0 until len) {
val x = elem(i)
val y = widen(f(x))
if (widen(x) ne y) {
if (mapped eq elems) mapped = new Array[AnyRef](len)
mapped(i) = y
}
}
if (mapped eq elems) this.asInstanceOf[ArrayIterator[B]]
else new ArrayIterator(mapped, len)
}
override def flatMap[B](f: A => IterableOnce[B]): ArrayIterator[B] =
flatten(map(f(_).buildIterator))
override def ++[B >: A](that: IterableOnce[B]): ArrayIterator[B] = {
val thatIterator @ ArrayIterator(elems2, len2) = fromIterator(that.iterator)
if (len == 0) thatIterator
else if (len2 == 0) this
else {
val resLen = len + len2
val resElems = new Array[AnyRef](resLen)
Array.copy(elems, 0, resElems, 0, len)
Array.copy(elems2, 0, resElems, len, len2)
new ArrayIterator(resElems, resLen)
}
}
}
object ArrayIterator {
private def widen(x: Any): AnyRef = x.asInstanceOf[AnyRef]
def fromIterator[A](it: Iterator[A]): ArrayIterator[A] = it match {
case it: ArrayIterator[A] => it
case _ =>
var elems = new Array[AnyRef](32)
var len = 0
def ensureCapacity() = {
while (len > elems.length) {
val newElems = new Array[AnyRef](elems.length * 2)
Array.copy(elems, 0, newElems, 0, elems.length)
elems = newElems
}
}
while (it.hasNext) {
len += 1
ensureCapacity()
elems(len - 1) = widen(it.next)
}
ArrayIterator(elems, len)
}
def flatten[A](its: ArrayIterator[Iterator[A]]): ArrayIterator[A] = {
var arrayIts = its.map(fromIterator)
var totalLen = 0
arrayIts.foreach(totalLen += _.len)
val allElems = new Array[AnyRef](totalLen)
var j = 0
arrayIts.foreach { it =>
Array.copy(it.elems, 0, allElems, j, it.len)
j += it.len
}
new ArrayIterator(allElems, totalLen)
}
}
}