diff options
author | Martin Odersky <odersky@gmail.com> | 2016-04-17 16:42:40 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-04-17 16:42:40 +0200 |
commit | b8472d8c6e6c9a267088817eb8e05577e5eda60b (patch) | |
tree | b98790c277e83fac25995a6cc3fcc75dbf4290b0 /tests/run/colltest5 | |
parent | 8cb73c0f5ca8bd809d0b9d7549951678f2240a61 (diff) | |
download | dotty-b8472d8c6e6c9a267088817eb8e05577e5eda60b.tar.gz dotty-b8472d8c6e6c9a267088817eb8e05577e5eda60b.tar.bz2 dotty-b8472d8c6e6c9a267088817eb8e05577e5eda60b.zip |
Updates of strawman
Bring strawman-4 and strawman-5 to feature-parity.
Test also strawman-4.
Diffstat (limited to 'tests/run/colltest5')
-rw-r--r-- | tests/run/colltest5/CollectionStrawMan5_1.scala | 94 | ||||
-rw-r--r-- | tests/run/colltest5/CollectionTests_2.scala | 4 |
2 files changed, 52 insertions, 46 deletions
diff --git a/tests/run/colltest5/CollectionStrawMan5_1.scala b/tests/run/colltest5/CollectionStrawMan5_1.scala index aa127cb7e..1a89d9659 100644 --- a/tests/run/colltest5/CollectionStrawMan5_1.scala +++ b/tests/run/colltest5/CollectionStrawMan5_1.scala @@ -3,6 +3,7 @@ package strawman.collections import Predef.{augmentString => _, wrapString => _, _} import scala.reflect.ClassTag import annotation.unchecked.uncheckedVariance +import annotation.tailrec /** A strawman architecture for new collections. It contains some * example collection classes and methods with the intent to expose @@ -32,30 +33,8 @@ object CollectionStrawMan5 { def apply[A](xs: A*): C[A] = fromIterable(View.Elems(xs: _*)) } - /** Base trait for Iterable operations */ - trait IterableLike[+A, +C[X] <: Iterable[X]] - extends FromIterable[C] - with IterableOps[A] - with IterableMonoTransforms[A @uncheckedVariance, C[A @uncheckedVariance]] - with IterablePolyTransforms[A @uncheckedVariance, C] { - protected def fromLikeIterable(coll: Iterable[A @uncheckedVariance]): C[A @uncheckedVariance] = fromIterable(coll) - } - - /** Base trait for Seq operations */ - trait SeqLike[+A, +C[X] <: Seq[X]] extends IterableLike[A, C] { - def reverse: C[A @uncheckedVariance] = { - var xs: List[A] = Nil - var it = iterator - while (it.hasNext) xs = new Cons(it.next, xs) - fromLikeIterable(xs) - } - } - /** Base trait for generic collections */ trait Iterable[+A] extends IterableOnce[A] with IterableLike[A, Iterable] { - override def iterator: Iterator[A] - override def fromIterable[B](it: Iterable[B]): Iterable[B] - protected def coll: Iterable[A] = this def knownLength: Int = -1 } @@ -64,9 +43,9 @@ object CollectionStrawMan5 { trait Seq[+A] extends Iterable[A] with SeqLike[A, Seq] { def apply(i: Int): A def length: Int - override def iterator: Iterator[A] } + /** Base trait for strict collections */ trait Buildable[+A, +To <: Iterable[A]] extends Iterable[A] { protected[this] def newBuilder: Builder[A, To] override def partition(p: A => Boolean): (To, To) = { @@ -74,8 +53,11 @@ object CollectionStrawMan5 { iterator.foreach(x => (if (p(x)) l else r) += x) (l.result, r.result) } + // one might also override other transforms here to avoid generating + // iterators if it helps efficiency. } + /** Base trait for collection builders */ trait Builder[-A, +To] { def +=(x: A): this.type def result: To @@ -88,6 +70,29 @@ object CollectionStrawMan5 { /* ------------ Operations ----------------------------------- */ + /** Base trait for Iterable operations + * + * VarianceNote + * ============ + * + * We require that for all child classes of Iterable the variance of + * the child class and the variance of the `C` parameter passed to `IterableLike` + * are the same. We cannot express this since we lack variance polymorphism. That's + * why we have to resort at some places to write `C[A @uncheckedVariance]`. + * + */ + trait IterableLike[+A, +C[X] <: Iterable[X]] + extends FromIterable[C] + with IterableOps[A] + with IterableMonoTransforms[A, C[A @uncheckedVariance]] // sound bcs of VarianceNote + with IterablePolyTransforms[A, C] { + protected[this] def fromLikeIterable(coll: Iterable[A]): C[A] = fromIterable(coll) + } + + /** Base trait for Seq operations */ + trait SeqLike[+A, +C[X] <: Seq[X]] + extends IterableLike[A, C] with SeqMonoTransforms[A, C[A @uncheckedVariance]] // sound bcs of VarianceNote + trait IterableOps[+A] extends Any { def iterator: Iterator[A] def foreach(f: A => Unit): Unit = iterator.foreach(f) @@ -99,16 +104,19 @@ object CollectionStrawMan5 { def view: View[A] = View.fromIterator(iterator) } - trait IterableMonoTransforms[A, +Repr] extends Any { + trait IterableMonoTransforms[+A, +Repr] extends Any { protected def coll: Iterable[A] - protected def fromLikeIterable(coll: Iterable[A]): Repr + protected[this] def fromLikeIterable(coll: Iterable[A]): Repr def filter(p: A => Boolean): Repr = fromLikeIterable(View.Filter(coll, p)) def partition(p: A => Boolean): (Repr, Repr) = { val pn = View.Partition(coll, p) (fromLikeIterable(pn.left), fromLikeIterable(pn.right)) } def drop(n: Int): Repr = fromLikeIterable(View.Drop(coll, n)) - def to[C[X] <: Iterable[X]](fi: FromIterable[C]): C[A] = fi.fromIterable(coll) + def to[C[X] <: Iterable[X]](fi: FromIterable[C]): C[A @uncheckedVariance] = + // variance seems sound because `to` could just as well have been added + // as a decorator. We should investigate this further to be sure. + fi.fromIterable(coll) } trait IterablePolyTransforms[+A, +C[A]] extends Any { @@ -118,9 +126,10 @@ object CollectionStrawMan5 { def flatMap[B](f: A => IterableOnce[B]): C[B] = fromIterable(View.FlatMap(coll, f)) def ++[B >: A](xs: IterableOnce[B]): C[B] = fromIterable(View.Concat(coll, xs)) def zip[B](xs: IterableOnce[B]): C[(A @uncheckedVariance, B)] = fromIterable(View.Zip(coll, xs)) + // sound bcs of VarianceNote } - trait SeqMonoTransforms[A, +Repr] extends Any with IterableMonoTransforms[A, Repr] { + trait SeqMonoTransforms[+A, +Repr] extends Any with IterableMonoTransforms[A, Repr] { def reverse: Repr = { var xs: List[A] = Nil var it = coll.iterator @@ -156,10 +165,12 @@ object CollectionStrawMan5 { case xs: List[B] => this ++: xs case _ => super.++(xs) } - override def reverse = super.reverse + @tailrec final override def drop(n: Int) = + if (n > 0) tail.drop(n - 1) else this } - case class Cons[+A](x: A, private[collections] var next: List[A @uncheckedVariance]) extends List[A] { + case class Cons[+A](x: A, private[collections] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally + extends List[A] { override def isEmpty = false override def head = x def tail = next @@ -182,11 +193,7 @@ object CollectionStrawMan5 { class ListBuffer[A] extends Seq[A] with SeqLike[A, ListBuffer] with Builder[A, List[A]] { private var first, last: List[A] = Nil private var aliased = false - def iterator = new Iterator[A] { - var current: List[A] = first - def hasNext = ??? - def next = ??? - } + def iterator = first.iterator def fromIterable[B](coll: Iterable[B]) = ListBuffer.fromIterable(coll) def apply(i: Int) = first.apply(i) def length = first.length @@ -211,6 +218,12 @@ object CollectionStrawMan5 { last = last1 this } + override def toString: String = + if (first.isEmpty) "ListBuffer()" + else { + val b = new StringBuilder("ListBuffer(").append(first.head) + first.tail.foldLeft(b)(_.append(", ").append(_)).append(")").toString + } } object ListBuffer extends IterableFactory[ListBuffer] { @@ -297,12 +310,12 @@ object CollectionStrawMan5 { def fromIterable[B](coll: Iterable[B]): List[B] = List.fromIterable(coll) def map(f: Char => Char): String = { val sb = new StringBuilder - for (ch <- StringOps(s)) sb.append(f(ch)) + for (ch <- s) sb.append(f(ch)) sb.toString } def flatMap(f: Char => String): String = { val sb = new StringBuilder - for (ch <- StringOps(s)) sb.append(f(ch)) + for (ch <- s) sb.append(f(ch)) sb.toString } def ++(xs: IterableOnce[Char]): String = { @@ -399,15 +412,6 @@ object CollectionStrawMan5 { -1 } } - case class Reverse[A](underlying: Iterable[A]) extends View[A] { - def iterator = { - var xs: List[A] = Nil - val it = underlying.iterator - while (it.hasNext) xs = Cons(it.next(), xs) - xs.iterator - } - override def knownLength = underlying.knownLength - } } /* ---------- Iterators ---------------------------------------------------*/ diff --git a/tests/run/colltest5/CollectionTests_2.scala b/tests/run/colltest5/CollectionTests_2.scala index cdff2e260..0961180ed 100644 --- a/tests/run/colltest5/CollectionTests_2.scala +++ b/tests/run/colltest5/CollectionTests_2.scala @@ -124,7 +124,7 @@ object Test { val ys9: Seq[Int] = xs9 val xs9a = xs.map(_.toUpper) // !!! need a language change to make this work without the : Char val ys9a: String = xs9a - val xs10 = xs.flatMap(x => s"$x,$x") + val xs10 = xs.flatMap((x: Char) => s"$x,$x") val ys10: String = xs10 val xs11 = xs ++ xs val ys11: String = xs11 @@ -161,9 +161,11 @@ object Test { def main(args: Array[String]) = { val ints = Cons(1, Cons(2, Cons(3, Nil))) val intsBuf = ints.to(ArrayBuffer) + val intsListBuf = ints.to(ListBuffer) val intsView = ints.view seqOps(ints) seqOps(intsBuf) + seqOps(intsListBuf) viewOps(intsView) stringOps("abc") } |