aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/strawman/collections/CollectionStrawMan1.scala (renamed from src/dotty/collections/CollectionStrawMan1.scala)147
-rw-r--r--tests/run/CollectionTests.check20
2 files changed, 96 insertions, 71 deletions
diff --git a/src/dotty/collections/CollectionStrawMan1.scala b/src/strawman/collections/CollectionStrawMan1.scala
index ea26eb932..93d4086f2 100644
--- a/src/dotty/collections/CollectionStrawMan1.scala
+++ b/src/strawman/collections/CollectionStrawMan1.scala
@@ -2,7 +2,6 @@ package strawman.collections
import Predef.{augmentString => _, wrapString => _, _}
import scala.reflect.ClassTag
-import collection.mutable.ListBuffer
/** A strawman architecture for new collections. It contains some
* example collection classes and methods with the intent to expose
@@ -36,11 +35,11 @@ object CollectionStrawMan1 {
}
/** Base trait for generic collections */
- trait Iterable[+IA] extends HasIterator[IA] with FromIterator[Iterable]
+ trait Iterable[+A] extends HasIterator[A] with FromIterator[Iterable]
/** Base trait for sequence collections */
- trait Seq[+AA] extends Iterable[AA] with FromIterator[Seq] {
- def apply(i: Int): AA
+ trait Seq[+A] extends Iterable[A] with FromIterator[Seq] {
+ def apply(i: Int): A
def length: Int
}
@@ -53,6 +52,7 @@ object CollectionStrawMan1 {
def foldLeft[B](z: B)(op: (B, A) => B): B = iterator.foldLeft(z)(op)
def foldRight[B](z: B)(op: (A, B) => B): B = iterator.foldRight(z)(op)
def indexWhere(p: A => Boolean): Int = iterator.indexWhere(p)
+ def isEmpty: Boolean = !iterator.hasNext
def head: A = iterator.next
def view: View[A] = new View(iterator)
def collect[C[X] <: Iterable[X]](fi: FromIterator[C]): C[A] = fi.fromIterator(iterator)
@@ -134,7 +134,13 @@ object CollectionStrawMan1 {
def tail = xs
}
- case object List extends IterableFactory[List] {
+ case object Nil extends List[Nothing] {
+ def isEmpty = true
+ def head = ???
+ def tail = ???
+ }
+
+ object List extends IterableFactory[List] {
def fromIterator[B](it: Iterator[B]): List[B] = it match {
case it: ListIterator[B] => it.toList
case _ => if (it.hasNext) Cons(it.next, fromIterator(it)) else Nil
@@ -148,50 +154,62 @@ object CollectionStrawMan1 {
def toList = current
}
- case object Nil extends List[Nothing] {
- def isEmpty = true
- def head = ???
- def tail = ???
- }
-
/** Concrete collection type: ArrayBuffer */
- class ArrayBuffer[A] private (initElems: Array[AnyRef], initLen: Int = 0) extends Seq[A] with FromIterator[ArrayBuffer] {
- def this() = this(new Array[AnyRef](16))
+ class ArrayBuffer[A] private (initElems: Array[AnyRef], initLength: Int) extends Seq[A] with FromIterator[ArrayBuffer] {
+ def this() = this(new Array[AnyRef](16), 0)
private var elems: Array[AnyRef] = initElems
- private var len = 0
- def apply(i: Int) = elems(i).asInstanceOf[A]
- def length = len
- def iterator = new RandomAccessIterator[A] {
- override val knownLength = len
- def apply(n: Int) = elems(n).asInstanceOf[A]
- }
+ private var start = 0
+ private var limit = initLength
+ def apply(i: Int) = elems(start + i).asInstanceOf[A]
+ def length = limit - start
+ def iterator = new ArrayBufferIterator[A](elems, start, length)
def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] =
ArrayBuffer.fromIterator(it)
def +=(elem: A): this.type = {
- if (len == elems.length) {
- val newelems = new Array[AnyRef](len * 2)
- Array.copy(elems, 0, newelems, 0, len)
- elems = newelems
+ if (limit == elems.length) {
+ if (start > 0) {
+ Array.copy(elems, start, elems, 0, length)
+ limit -= start
+ start = 0
+ }
+ else {
+ val newelems = new Array[AnyRef](limit * 2)
+ Array.copy(elems, 0, newelems, 0, limit)
+ elems = newelems
+ }
}
- elems(len) = elem.asInstanceOf[AnyRef]
- len += 1
+ elems(limit) = elem.asInstanceOf[AnyRef]
+ limit += 1
this
}
- override def toString = elems.take(len).deep.toString
+ def trimStart(n: Int): Unit = start += (n max 0)
+ override def toString = s"ArrayBuffer(${elems.slice(start, limit).mkString(", ")})"
}
object ArrayBuffer extends IterableFactory[ArrayBuffer] {
- def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] =
- if (it.knownLength == 0) {
- val elems = new Array[AnyRef](it.knownLength)
+ def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] = it match {
+ case Iterator.Concat(fst: ArrayBufferIterator[_], snd: ArrayBufferIterator[_]) =>
+ val elems = new Array[AnyRef](fst.remaining + snd.remaining)
+ Array.copy(fst.elems, fst.start, elems, 0, fst.remaining)
+ Array.copy(snd.elems, snd.start, elems, fst.remaining, snd.remaining)
+ new ArrayBuffer(elems, elems.length)
+ case it @ Iterator.Partition(underlying, _, buf, _) =>
+ while (underlying.hasNext) it.distribute()
+ buf.asInstanceOf[ArrayBuffer[B]]
+ case it if it.remaining >= 0 =>
+ val elems = new Array[AnyRef](it.remaining)
for (i <- 0 until elems.length) elems(i) = it.next.asInstanceOf[AnyRef]
- new ArrayBuffer(elems)
- }
- else {
+ new ArrayBuffer[B](elems, elems.length)
+ case _ =>
val buf = new ArrayBuffer[B]
while (it.hasNext) buf += it.next
buf
- }
+ }
+ }
+
+ class ArrayBufferIterator[A](val elems: Array[AnyRef], initStart: Int, length: Int) extends RandomAccessIterator[A] {
+ val limit = length
+ def apply(n: Int) = elems(initStart + n).asInstanceOf[A]
}
/** Concrete collection type: View */
@@ -219,7 +237,7 @@ object CollectionStrawMan1 {
/** Concrete collection type: String */
implicit class StringOps(val s: String) extends AnyVal with Ops[Char] {
def iterator: Iterator[Char] = new RandomAccessIterator[Char] {
- override val knownLength = s.length
+ override val limit = s.length
def apply(n: Int) = s.charAt(n)
}
}
@@ -281,7 +299,7 @@ object CollectionStrawMan1 {
def flatMap[B](f: A => CanIterate[B]): Iterator[B] = Iterator.FlatMap(this, f)
def ++[B >: A](xs: CanIterate[B]): Iterator[B] = Iterator.Concat(this, xs.iterator)
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
- val lookaheadTrue, lookaheadFalse = new ListBuffer[A]
+ val lookaheadTrue, lookaheadFalse = new ArrayBuffer[A]
(Iterator.Partition(this, p, lookaheadTrue, lookaheadFalse),
Iterator.Partition[A](this, !p(_), lookaheadFalse, lookaheadTrue))
}
@@ -292,18 +310,26 @@ object CollectionStrawMan1 {
while (hasNext) elems = Cons(next, elems)
elems.iterator
}
+
+ /** If this iterator results from applying a transfomation to another iterator,
+ * that other iterator, otherwise the iterator itself.
+ */
def underlying: Iterator[_] = this
- def knownLength = -1
+
+ /** If the number of elements still to be returned by this iterator is known,
+ * that number, otherwise -1.
+ */
+ def remaining = -1
}
object Iterator {
val empty: Iterator[Nothing] = new Iterator[Nothing] {
def hasNext = false
def next = ???
- override val knownLength = 0
+ override def remaining = 0
}
def apply[A](xs: A*): Iterator[A] = new RandomAccessIterator[A] {
- override val knownLength = xs.length
+ override val limit = xs.length
def apply(n: Int) = xs(n)
}
def nextOnEmpty = throw new NoSuchElementException("next on empty iterator")
@@ -311,7 +337,7 @@ object CollectionStrawMan1 {
case class Map[A, B](override val underlying: Iterator[A], f: A => B) extends Iterator[B] {
def hasNext = underlying.hasNext
def next = f(underlying.next)
- override val knownLength = underlying.knownLength
+ override def remaining = underlying.remaining
}
case class FlatMap[A, B](override val underlying: Iterator[A], f: A => CanIterate[B]) extends Iterator[B] {
private var myCurrent: Iterator[B] = Iterator.empty
@@ -331,19 +357,18 @@ object CollectionStrawMan1 {
}
def hasNext = current.hasNext
def next = current.next
- override val knownLength =
- if (underlying.knownLength > 0 && other.knownLength > 0)
- underlying.knownLength + other.knownLength
+ override def remaining =
+ if (underlying.remaining >= 0 && other.remaining >= 0)
+ underlying.remaining + other.remaining
else -1
}
- case class Partition[A](override val underlying: Iterator[A], p: A => Boolean, lookahead: ListBuffer[A], dual: ListBuffer[A]) extends Iterator[A] {
+ case class Partition[A](override val underlying: Iterator[A], p: A => Boolean, lookahead: ArrayBuffer[A], dual: ArrayBuffer[A]) extends Iterator[A] {
+ def distribute() = {
+ val elem = underlying.next
+ (if (p(elem)) lookahead else dual) += elem
+ }
final def hasNext: Boolean =
- lookahead.nonEmpty ||
- underlying.hasNext && {
- val elem = underlying.next
- (if (p(elem)) lookahead else dual) += elem
- hasNext
- }
+ !lookahead.isEmpty || underlying.hasNext && { distribute(); hasNext }
final def next =
if (hasNext) {
val r = lookahead.head
@@ -356,27 +381,27 @@ object CollectionStrawMan1 {
def hasNext: Boolean = underlying.hasNext && (
toSkip == 0 || { underlying.next; toSkip -= 1; hasNext })
def next = if (hasNext) underlying.next else nextOnEmpty
- override val knownLength = (underlying.knownLength - n) max -1
+ override def remaining = (underlying.remaining - toSkip) max -1
}
case class Zip[A, B](override val underlying: Iterator[A], other: Iterator[B]) extends Iterator[(A, B)] {
def hasNext = underlying.hasNext && other.hasNext
def next = (underlying.next, other.next)
- override val knownLength = underlying.knownLength min other.knownLength
+ override def remaining = underlying.remaining min other.remaining
}
- class Reverse[A](underlying: RandomAccessIterator[A]) extends RandomAccessIterator[A] {
- override val knownLength = underlying.knownLength
- def apply(n: Int) = underlying.apply(knownLength - 1 - n)
+ case class Reverse[A](override val underlying: RandomAccessIterator[A]) extends RandomAccessIterator[A] {
+ def apply(n: Int) = underlying.apply(underlying.limit - 1 - n)
+ def limit = underlying.remaining
}
}
trait RandomAccessIterator[+A] extends Iterator[A] { self =>
def apply(n: Int): A
- def knownLength: Int
- def length: Int = knownLength
- private var cur = 0
- def hasNext = cur < knownLength
- def next: A = { val r = this(cur); cur += 1; r }
- override def drop(n: Int): Iterator[A] = { cur += (n max 0); this }
+ def limit: Int
+ var start = 0
+ override def remaining = (limit - start) max 0
+ def hasNext = start < limit
+ def next: A = { val r = this(start); start += 1; r }
+ override def drop(n: Int): Iterator[A] = { start += (n max 0); this }
override def reverse: Iterator[A] = new Iterator.Reverse(this)
}
}
diff --git a/tests/run/CollectionTests.check b/tests/run/CollectionTests.check
index 7c4f6e77a..6c61d8821 100644
--- a/tests/run/CollectionTests.check
+++ b/tests/run/CollectionTests.check
@@ -21,17 +21,17 @@ Cons(3,Cons(2,Cons(1,Nil)))
1
1
Cons(1,Cons(2,Cons(3,Nil)))
-Array(2)
-Array(1, 3)
-Array(3)
-Array(true, true, true)
-Array(1, -1, 2, -2, 3, -3)
-Array(1, 2, 3, 1, 2, 3)
-Array(1, 2, 3)
+ArrayBuffer(2)
+ArrayBuffer(1, 3)
+ArrayBuffer(3)
+ArrayBuffer(true, true, true)
+ArrayBuffer(1, -1, 2, -2, 3, -3)
+ArrayBuffer(1, 2, 3, 1, 2, 3)
+ArrayBuffer(1, 2, 3)
Cons(1,Cons(2,Cons(3,Nil)))
-Array(1, 2, 3, a)
-Array((1,true), (2,true), (3,true))
-Array(3, 2, 1)
+ArrayBuffer(1, 2, 3, a)
+ArrayBuffer((1,true), (2,true), (3,true))
+ArrayBuffer(3, 2, 1)
-------
123
123