From 0db7566162e973f1c22d8fb22633904cc5477cb7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 May 2017 13:53:59 +0200 Subject: [PATCH 1/8] Expose factories in collections. This allows to convert any collection to the dynamic type of any other by writing e.g. xs.to(ys.iterableFactory) Also: Define IterableFactory.empty in terms of fromIterable --- .../scala/strawman/collection/ArrayOps.scala | 3 ++- .../scala/strawman/collection/Factories.scala | 6 +++--- .../scala/strawman/collection/Iterable.scala | 6 +++++- .../scala/strawman/collection/StringOps.scala | 2 +- src/main/scala/strawman/collection/View.scala | 19 +++++++++++++------ .../collection/immutable/BitSet.scala | 3 ++- .../collection/immutable/HashMap.scala | 2 +- .../collection/immutable/HashSet.scala | 5 +++-- .../collection/immutable/LazyList.scala | 5 +++-- .../strawman/collection/immutable/List.scala | 6 +++--- .../collection/immutable/ListMap.scala | 2 +- .../collection/immutable/ListSet.scala | 4 ++-- .../collection/immutable/TreeMap.scala | 2 +- .../collection/immutable/TreeSet.scala | 2 +- .../collection/mutable/ArrayBuffer.scala | 8 ++++---- .../strawman/collection/mutable/BitSet.scala | 3 +-- .../strawman/collection/mutable/HashSet.scala | 6 ++---- .../collection/mutable/ListBuffer.scala | 10 ++++++---- .../strawman/collection/mutable/Map.scala | 4 ++-- .../strawman/collection/mutable/TreeSet.scala | 4 ++-- 20 files changed, 58 insertions(+), 44 deletions(-) diff --git a/src/main/scala/strawman/collection/ArrayOps.scala b/src/main/scala/strawman/collection/ArrayOps.scala index 8561d7c294..4a9ac20a85 100644 --- a/src/main/scala/strawman/collection/ArrayOps.scala +++ b/src/main/scala/strawman/collection/ArrayOps.scala @@ -21,9 +21,10 @@ class ArrayOps[A](val xs: Array[A]) def elemTag: ClassTag[A] = ClassTag(xs.getClass.getComponentType) + def iterableFactory = immutable.Seq + protected[this] def fromTaggedIterable[B: ClassTag](coll: Iterable[B]): Array[B] = coll.toArray[B] protected[this] def fromSpecificIterable(coll: Iterable[A]): Array[A] = coll.toArray[A](elemTag) - protected[this] def fromIterable[B](coll: Iterable[B]): immutable.Seq[B] = immutable.Seq.fromIterable(coll) protected[this] def newBuilder = new ArrayBuffer[A].mapResult(_.toArray(elemTag)) diff --git a/src/main/scala/strawman/collection/Factories.scala b/src/main/scala/strawman/collection/Factories.scala index 2437e440f9..13a036541e 100644 --- a/src/main/scala/strawman/collection/Factories.scala +++ b/src/main/scala/strawman/collection/Factories.scala @@ -18,7 +18,7 @@ trait IterableFactory[+CC[_]] { def fromIterable[E](it: Iterable[E]): CC[E] - def empty[A]: CC[A] + def empty[A]: CC[A] = fromIterable(View.Empty) def apply[A](xs: A*): CC[A] = fromIterable(View.Elems(xs: _*)) @@ -35,7 +35,7 @@ object IterableFactory { } class Delegate[CC[_]](delegate: IterableFactory[CC]) extends IterableFactory[CC] { - def empty[A]: CC[A] = delegate.empty + override def empty[A]: CC[A] = delegate.empty def fromIterable[E](it: Iterable[E]): CC[E] = delegate.fromIterable(it) } @@ -124,4 +124,4 @@ object OrderedMapFactory { def orderedFromIterable[K: Ordering, V](it: Iterable[(K, V)]): CC[K, V] = delegate.orderedFromIterable(it) } -} \ No newline at end of file +} diff --git a/src/main/scala/strawman/collection/Iterable.scala b/src/main/scala/strawman/collection/Iterable.scala index b05ad7daa7..cf88727eb5 100644 --- a/src/main/scala/strawman/collection/Iterable.scala +++ b/src/main/scala/strawman/collection/Iterable.scala @@ -29,8 +29,12 @@ trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterabl trait IterableOps[+A, +CC[X], +C] extends Any { protected def coll: Iterable[A] + protected[this] def fromSpecificIterable(coll: Iterable[A]): C - protected[this] def fromIterable[E](it: Iterable[E]): CC[E] + + def iterableFactory: IterableFactory[CC] + + protected[this] def fromIterable[E](it: Iterable[E]): CC[E] = iterableFactory.fromIterable(it) /** Apply `f` to each element for its side effects * Note: [U] parameter needed to help scalac's type inference. diff --git a/src/main/scala/strawman/collection/StringOps.scala b/src/main/scala/strawman/collection/StringOps.scala index 5801fa3be9..1da1bc3976 100644 --- a/src/main/scala/strawman/collection/StringOps.scala +++ b/src/main/scala/strawman/collection/StringOps.scala @@ -22,7 +22,7 @@ class StringOps(val s: String) sb.result } - protected[this] def fromIterable[E](coll: Iterable[E]): List[E] = List.fromIterable(coll) + def iterableFactory = List protected[this] def newBuilder = new StringBuilder diff --git a/src/main/scala/strawman/collection/View.scala b/src/main/scala/strawman/collection/View.scala index 4174cfc74b..d98fa8928f 100644 --- a/src/main/scala/strawman/collection/View.scala +++ b/src/main/scala/strawman/collection/View.scala @@ -7,11 +7,8 @@ import scala.Predef.intWrapper trait View[+A] extends Iterable[A] with IterableOps[A, View, View[A]] { override def view = this - /** Avoid copying if source collection is already a view. */ - override def fromIterable[B](c: Iterable[B]): View[B] = c match { - case c: View[B] => c - case _ => View.fromIterator(c.iterator()) - } + def iterableFactory = View + override protected[this] def fromSpecificIterable(coll: Iterable[A]): View[A] = fromIterable(coll) @@ -19,11 +16,21 @@ trait View[+A] extends Iterable[A] with IterableOps[A, View, View[A]] { } /** This object reifies operations on views as case classes */ -object View { +object View extends IterableFactory[View] { + def fromIterator[A](it: => Iterator[A]): View[A] = new View[A] { def iterator() = it } + /** Avoid copying if source collection is already a view. */ + def fromIterable[E](it: Iterable[E]): View[E] = it match { + case it: View[E] => it + case _ => View.fromIterator(it.iterator()) + } + + override def empty[A]: View[A] = Empty + override def apply[A](xs: A*): View[A] = Elems(xs: _*) + /** The empty view */ case object Empty extends View[Nothing] { def iterator() = Iterator.empty diff --git a/src/main/scala/strawman/collection/immutable/BitSet.scala b/src/main/scala/strawman/collection/immutable/BitSet.scala index de9a2ea1e6..ff2a078696 100644 --- a/src/main/scala/strawman/collection/immutable/BitSet.scala +++ b/src/main/scala/strawman/collection/immutable/BitSet.scala @@ -26,7 +26,8 @@ sealed abstract class BitSet def empty: BitSet = BitSet.empty - protected[this] def fromIterable[B](coll: collection.Iterable[B]): Set[B] = Set.fromIterable(coll) + def iterableFactory = Set + protected[this] def fromSpecificIterable(coll: collection.Iterable[Int]): BitSet = BitSet.fromSpecificIterable(coll) protected[this] def orderedFromIterable[B : Ordering](it: collection.Iterable[B]): SortedSet[B] = SortedSet.orderedFromIterable(it) diff --git a/src/main/scala/strawman/collection/immutable/HashMap.scala b/src/main/scala/strawman/collection/immutable/HashMap.scala index bfa4118b66..26778f57c5 100644 --- a/src/main/scala/strawman/collection/immutable/HashMap.scala +++ b/src/main/scala/strawman/collection/immutable/HashMap.scala @@ -33,7 +33,7 @@ sealed trait HashMap[K, +V] import HashMap.{bufferSize, liftMerger, Merger, MergeFunction, nullToEmpty} - protected[this] def fromIterable[E](it: collection.Iterable[E]): Iterable[E] = List.fromIterable(it) + def iterableFactory = List protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)]): HashMap[K, V] = HashMap.fromIterable(coll) diff --git a/src/main/scala/strawman/collection/immutable/HashSet.scala b/src/main/scala/strawman/collection/immutable/HashSet.scala index f0a08fceab..f7effc8d27 100644 --- a/src/main/scala/strawman/collection/immutable/HashSet.scala +++ b/src/main/scala/strawman/collection/immutable/HashSet.scala @@ -30,7 +30,8 @@ sealed trait HashSet[A] import HashSet.nullToEmpty - protected[this] def fromIterable[B](coll: collection.Iterable[B]): HashSet[B] = HashSet.fromIterable(coll) + def iterableFactory = HashSet + protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): HashSet[A] = fromIterable(coll) def contains(elem: A): Boolean = get0(elem, computeHash(elem), 0) @@ -59,7 +60,7 @@ object HashSet extends IterableFactory[HashSet] { case _ => empty ++ it } - def empty[A <: Any]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]] + override def empty[A]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]] private object EmptyHashSet extends HashSet[Any] { diff --git a/src/main/scala/strawman/collection/immutable/LazyList.scala b/src/main/scala/strawman/collection/immutable/LazyList.scala index 655a28750a..2d55d81ee4 100644 --- a/src/main/scala/strawman/collection/immutable/LazyList.scala +++ b/src/main/scala/strawman/collection/immutable/LazyList.scala @@ -32,7 +32,8 @@ class LazyList[+A](expr: => LazyList.Evaluated[A]) def #:: [B >: A](elem: => B): LazyList[B] = new LazyList(Some((elem, this))) - protected[this] def fromIterable[B](coll: collection.Iterable[B]): LazyList[B] = LazyList.fromIterable(coll) + def iterableFactory = LazyList + protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): LazyList[A] = fromIterable(coll) override def className = "LazyList" @@ -66,5 +67,5 @@ object LazyList extends IterableFactory[LazyList] { def newBuilder[A]: Builder[A, LazyList[A]] = ??? - def empty[A]: LazyList[A] = new LazyList[A](None) + override def empty[A]: LazyList[A] = new LazyList[A](None) } diff --git a/src/main/scala/strawman/collection/immutable/List.scala b/src/main/scala/strawman/collection/immutable/List.scala index 330f357281..bcde5950da 100644 --- a/src/main/scala/strawman/collection/immutable/List.scala +++ b/src/main/scala/strawman/collection/immutable/List.scala @@ -15,7 +15,8 @@ sealed trait List[+A] with SeqOps[A, List, List[A]] with Buildable[A, List[A]] { - protected[this] def fromIterable[B](c: collection.Iterable[B]): List[B] = List.fromIterable(c) + def iterableFactory = List + protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): List[A] = fromIterable(coll) protected[this] def newBuilder = List.newBuilder[A] @@ -63,6 +64,5 @@ object List extends IterableFactory[List] { def newBuilder[A]: Builder[A, List[A]] = new ListBuffer[A].mapResult(_.toList) - def empty[A <: Any]: List[A] = Nil - + override def empty[A <: Any]: List[A] = Nil } diff --git a/src/main/scala/strawman/collection/immutable/ListMap.scala b/src/main/scala/strawman/collection/immutable/ListMap.scala index bc6d5fd1aa..b8b9ca56c0 100644 --- a/src/main/scala/strawman/collection/immutable/ListMap.scala +++ b/src/main/scala/strawman/collection/immutable/ListMap.scala @@ -48,7 +48,7 @@ sealed class ListMap[K, +V] with MapOps[K, V, ListMap, ListMap[K, V]] with Serializable { - protected[this] def fromIterable[E](it: collection.Iterable[E]): Iterable[E] = List.fromIterable(it) + def iterableFactory = List protected[this] def mapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)]): ListMap[K2,V2] = ListMap.fromIterable(it) diff --git a/src/main/scala/strawman/collection/immutable/ListSet.scala b/src/main/scala/strawman/collection/immutable/ListSet.scala index 98f962893a..a0d1ad67ce 100644 --- a/src/main/scala/strawman/collection/immutable/ListSet.scala +++ b/src/main/scala/strawman/collection/immutable/ListSet.scala @@ -59,7 +59,7 @@ sealed class ListSet[A] def toSet[B >: A]: Set[B] = this.asInstanceOf[ListSet[B]] - protected[this] def fromIterable[B](coll: collection.Iterable[B]): ListSet[B] = ListSet.fromIterable(coll) + def iterableFactory = ListSet protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): ListSet[A] = fromIterable(coll) /** @@ -122,7 +122,7 @@ object ListSet extends IterableFactory[ListSet] { private object EmptyListSet extends ListSet[Any] private[collection] def emptyInstance: ListSet[Any] = EmptyListSet - def empty[A <: Any]: ListSet[A] = EmptyListSet.asInstanceOf[ListSet[A]] + override def empty[A]: ListSet[A] = EmptyListSet.asInstanceOf[ListSet[A]] } diff --git a/src/main/scala/strawman/collection/immutable/TreeMap.scala b/src/main/scala/strawman/collection/immutable/TreeMap.scala index 2cba46a285..06ca234d36 100644 --- a/src/main/scala/strawman/collection/immutable/TreeMap.scala +++ b/src/main/scala/strawman/collection/immutable/TreeMap.scala @@ -36,7 +36,7 @@ final class TreeMap[K, +V] private (tree: RB.Tree[K, V])(implicit val ordering: def this()(implicit ordering: Ordering[K]) = this(null)(ordering) - protected[this] def fromIterable[E](it: collection.Iterable[E]): Iterable[E] = List.fromIterable(it) + def iterableFactory = List protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)]): TreeMap[K, V] = TreeMap.orderedFromIterable(coll) diff --git a/src/main/scala/strawman/collection/immutable/TreeSet.scala b/src/main/scala/strawman/collection/immutable/TreeSet.scala index 4510aed397..02cc5d6f31 100644 --- a/src/main/scala/strawman/collection/immutable/TreeSet.scala +++ b/src/main/scala/strawman/collection/immutable/TreeSet.scala @@ -61,7 +61,7 @@ final class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: O def keysIteratorFrom(start: A): Iterator[A] = RB.keysIterator(tree, Some(start)) - protected[this] def fromIterable[B](coll: strawman.collection.Iterable[B]): Set[B] = Set.fromIterable(coll) + def iterableFactory = Set protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[A]): TreeSet[A] = TreeSet.orderedFromIterable(coll) diff --git a/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala b/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala index 332100882f..e800b37132 100644 --- a/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala +++ b/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala @@ -45,8 +45,7 @@ class ArrayBuffer[A] private (initElems: Array[AnyRef], initLength: Int) def iterator() = view.iterator() - protected[this] def fromIterable[B](it: collection.Iterable[B]): ArrayBuffer[B] = - ArrayBuffer.fromIterable(it) + def iterableFactory = ArrayBuffer protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): ArrayBuffer[A] = fromIterable(coll) @@ -135,10 +134,11 @@ object ArrayBuffer extends IterableFactory[ArrayBuffer] { for (i <- 0 until array.length) array(i) = it.next().asInstanceOf[AnyRef] new ArrayBuffer[B](array, array.length) } - else Growable.fromIterable[B](empty, coll) + else new ArrayBuffer[B] ++= coll - def empty[A]: ArrayBuffer[A] = new ArrayBuffer[A]() + def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A]() + override def empty[A <: Any]: ArrayBuffer[A] = new ArrayBuffer[A]() } class ArrayBufferView[A](val array: Array[AnyRef], val length: Int) extends IndexedView[A] { diff --git a/src/main/scala/strawman/collection/mutable/BitSet.scala b/src/main/scala/strawman/collection/mutable/BitSet.scala index c768616eee..7b5fbb6c2b 100644 --- a/src/main/scala/strawman/collection/mutable/BitSet.scala +++ b/src/main/scala/strawman/collection/mutable/BitSet.scala @@ -34,8 +34,7 @@ class BitSet(protected[collection] final var elems: Array[Long]) def this() = this(0) - def fromIterable[B](coll: collection.Iterable[B]): collection.mutable.Set[B] = - collection.mutable.Set.fromIterable(coll) + def iterableFactory = Set protected[this] def orderedFromIterable[B : Ordering](it: collection.Iterable[B]): collection.mutable.SortedSet[B] = collection.mutable.SortedSet.orderedFromIterable(it) diff --git a/src/main/scala/strawman/collection/mutable/HashSet.scala b/src/main/scala/strawman/collection/mutable/HashSet.scala index 89dd6a009a..507cda3471 100644 --- a/src/main/scala/strawman/collection/mutable/HashSet.scala +++ b/src/main/scala/strawman/collection/mutable/HashSet.scala @@ -31,8 +31,7 @@ final class HashSet[A](contents: FlatHashTable.Contents[A]) override def iterator(): Iterator[A] = table.iterator - protected[this] def fromIterable[B](coll: strawman.collection.Iterable[B]): HashSet[B] = - HashSet.fromIterable(coll) + def iterableFactory = HashSet protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): HashSet[A] = fromIterable(coll) @@ -80,6 +79,5 @@ object HashSet extends IterableFactory[HashSet] { def fromIterable[B](it: strawman.collection.Iterable[B]): HashSet[B] = Growable.fromIterable(empty[B], it) - def empty[A]: HashSet[A] = new HashSet[A] - + override def empty[A]: HashSet[A] = new HashSet[A] } diff --git a/src/main/scala/strawman/collection/mutable/ListBuffer.scala b/src/main/scala/strawman/collection/mutable/ListBuffer.scala index 0fea843e33..0d240618d2 100644 --- a/src/main/scala/strawman/collection/mutable/ListBuffer.scala +++ b/src/main/scala/strawman/collection/mutable/ListBuffer.scala @@ -26,7 +26,8 @@ class ListBuffer[A] def iterator() = first.iterator() - protected[this] def fromIterable[B](c: collection.Iterable[B]) = ListBuffer.fromIterable(c) + def iterableFactory = ListBuffer + protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): ListBuffer[A] = fromIterable(coll) def apply(i: Int) = first.apply(i) @@ -201,8 +202,9 @@ class ListBuffer[A] object ListBuffer extends IterableFactory[ListBuffer] { - def fromIterable[A](coll: collection.Iterable[A]): ListBuffer[A] = Growable.fromIterable(empty[A], coll) - - def empty[A]: ListBuffer[A] = new ListBuffer[A] + def fromIterable[A](coll: collection.Iterable[A]): ListBuffer[A] = new ListBuffer[A] ++= coll + def newBuilder[A]: Builder[A, ListBuffer[A]] = new ListBuffer[A] + + override def empty[A]: ListBuffer[A] = new ListBuffer[A] } diff --git a/src/main/scala/strawman/collection/mutable/Map.scala b/src/main/scala/strawman/collection/mutable/Map.scala index 9ef43c6845..ca42d1af1f 100644 --- a/src/main/scala/strawman/collection/mutable/Map.scala +++ b/src/main/scala/strawman/collection/mutable/Map.scala @@ -20,7 +20,7 @@ trait MapOps[K, V, +CC[X, Y] <: Map[X, Y], +C <: Map[K, V]] protected def coll: Map[K, V] - def fromIterable[B](coll: collection.Iterable[B]): Iterable[B] = Iterable.fromIterable(coll) + def iterableFactory = Iterable /** Adds a new key/value pair to this map and optionally returns previously bound value. * If the map already contains a @@ -89,4 +89,4 @@ trait MapOps[K, V, +CC[X, Y] <: Map[X, Y], +C <: Map[K, V]] } -object Map extends MapFactory.Delegate[Map](HashMap) \ No newline at end of file +object Map extends MapFactory.Delegate[Map](HashMap) diff --git a/src/main/scala/strawman/collection/mutable/TreeSet.scala b/src/main/scala/strawman/collection/mutable/TreeSet.scala index 1c57f8f4e3..3fe17a7aeb 100644 --- a/src/main/scala/strawman/collection/mutable/TreeSet.scala +++ b/src/main/scala/strawman/collection/mutable/TreeSet.scala @@ -43,7 +43,7 @@ sealed class TreeSet[A] private (tree: RB.Tree[A, Null])(implicit val ordering: protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): TreeSet[A] = TreeSet.orderedFromIterable(coll) - def fromIterable[B](coll: collection.Iterable[B]): Set[B] = Set.fromIterable(coll) + def iterableFactory = Set def keysIteratorFrom(start: A): collection.Iterator[A] = RB.keysIterator(tree, Some(start)) @@ -181,4 +181,4 @@ object TreeSet extends OrderedIterableFactory[TreeSet] { def orderedFromIterable[E : Ordering](it: collection.Iterable[E]): TreeSet[E] = Growable.fromIterable(empty[E], it) -} \ No newline at end of file +} From 359d96ea145e1c0d3d3bfec6225158343e569ac0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 May 2017 14:34:55 +0200 Subject: [PATCH 2/8] Revive part of TraverseTest The commit shows that the fully generic part of TraverseTest works. The rest is more tricky, but i am not convinced we need to support that. I mean, we can always define optionSequence specialized to individual types - there's not a lot to be gained to specify it separately for ordered collections. --- .../collection/test/TraverseTest.scala | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/test/scala/strawman/collection/test/TraverseTest.scala b/src/test/scala/strawman/collection/test/TraverseTest.scala index 159e50414a..f7c876a9bd 100644 --- a/src/test/scala/strawman/collection/test/TraverseTest.scala +++ b/src/test/scala/strawman/collection/test/TraverseTest.scala @@ -1,26 +1,28 @@ -//package strawman -// -//package collection.test -// -//import org.junit.Test -//import strawman.collection.Iterable -//import strawman.collection.mutable.Builder -//import strawman.collection._ -// -//import scala.{Any, Either, Int, Left, None, Option, Right, Some, Unit} -//import scala.Predef.ArrowAssoc -//import scala.math.Ordering -//import java.lang.String -// -//class TraverseTest { -// -// // You can either overload methods for PolyBuildable and OrderedPolyBuildable (if you want to support ordered collection types) -// def optionSequence1[C[X] <: Iterable[X] with PolyBuildable[X, C], A](xs: C[Option[A]]): Option[C[A]] = -// xs.foldLeft[Option[Builder[A, C[A]]]](Some(xs.newBuilder)) { -// case (Some(builder), Some(a)) => Some(builder += a) -// case _ => None -// }.map(_.result) -// +package strawman + +package collection.test + +import org.junit.Test +import strawman.collection.Iterable +import strawman.collection.mutable.{Builder, ArrayBuffer} +import strawman.collection._ + +import scala.{Any, Either, Int, Left, None, Option, Right, Some, Unit} +import scala.Predef.ArrowAssoc +import scala.math.Ordering +import java.lang.String + +class TraverseTest { + + // You can either overload methods for PolyBuildable and OrderedPolyBuildable (if you want to support ordered collection types) + def optionSequence1[C[X] <: Iterable[X] with IterableOps[X, C, _], A](xs: C[Option[A]]): Option[C[A]] = + xs.foldLeft[Option[ArrayBuffer[A]]](Some(new ArrayBuffer[A])) { (bo, xo) => + (bo, xo) match { + case (Some(builder), Some(a)) => Some(builder += a) + case _ => None + } + }.map(_.to(xs.iterableFactory)) + // def optionSequence1[CC[_], A](xs: OrderedPolyBuildable[Option[A], CC] with Iterable[Option[A]])(implicit ev: Ordering[A]): Option[CC[A]] = // xs.foldLeft[Option[Builder[A, CC[A]]]](Some(xs.newOrderedBuilder)) { // case (Some(builder), Some(a)) => Some(builder += a) @@ -40,18 +42,18 @@ // case (Left(a) , _) => Left(a) // case (_ , Left(a)) => Left(a) // }.right.map(_.result) -// -// @Test -// def optionSequence1Test: Unit = { -// val xs1 = immutable.List(Some(1), None, Some(2)) -// val o1 = optionSequence1(xs1) -// val o1t: Option[immutable.List[Int]] = o1 -// -// val xs2 = immutable.TreeSet(Some("foo"), Some("bar"), None) -// val o2 = optionSequence1(xs2) -// val o2t: Option[immutable.TreeSet[String]] = o2 -// } -// + + @Test + def optionSequence1Test: Unit = { + val xs1 = immutable.List(Some(1), None, Some(2)) + val o1 = optionSequence1(xs1) + val o1t: Option[immutable.List[Int]] = o1 + + val xs2 = immutable.TreeSet(Some("foo"), Some("bar"), None) + val o2 = optionSequence1(xs2) + val o2t: Option[immutable.Set[String]] = o2 + } + // def optionSequenceTest: Unit = { // val xs1 = immutable.List(Some(1), None, Some(2)) // val o1 = optionSequence(xs1) @@ -74,4 +76,5 @@ // val e1 = eitherSequence(xs3) // val e1t: Either[Int, mutable.ListBuffer[String]] = e1 // } -//} + +} From b58c0de63e96633494904bb71a7e6c64b3e39bfe Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 May 2017 14:44:47 +0200 Subject: [PATCH 3/8] Make traverse test compile under Scala2 --- src/test/scala/strawman/collection/test/TraverseTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/strawman/collection/test/TraverseTest.scala b/src/test/scala/strawman/collection/test/TraverseTest.scala index f7c876a9bd..936b39774b 100644 --- a/src/test/scala/strawman/collection/test/TraverseTest.scala +++ b/src/test/scala/strawman/collection/test/TraverseTest.scala @@ -49,7 +49,7 @@ class TraverseTest { val o1 = optionSequence1(xs1) val o1t: Option[immutable.List[Int]] = o1 - val xs2 = immutable.TreeSet(Some("foo"), Some("bar"), None) + val xs2: immutable.Set[Option[String]] = immutable.TreeSet(Some("foo"), Some("bar"), None) val o2 = optionSequence1(xs2) val o2t: Option[immutable.Set[String]] = o2 } From 898cf319f0f6ccdcc91b4c39a83a705f8f863a0f Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 17 May 2017 16:51:03 +0200 Subject: [PATCH 4/8] Remove default implementation of empty --- src/main/scala/strawman/collection/Factories.scala | 2 +- src/main/scala/strawman/collection/View.scala | 2 +- src/main/scala/strawman/collection/immutable/HashSet.scala | 2 +- src/main/scala/strawman/collection/immutable/LazyList.scala | 2 +- src/main/scala/strawman/collection/immutable/List.scala | 2 +- src/main/scala/strawman/collection/immutable/ListSet.scala | 2 +- src/main/scala/strawman/collection/mutable/ArrayBuffer.scala | 2 +- src/main/scala/strawman/collection/mutable/HashSet.scala | 2 +- src/main/scala/strawman/collection/mutable/ListBuffer.scala | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/scala/strawman/collection/Factories.scala b/src/main/scala/strawman/collection/Factories.scala index 13a036541e..f4d5f51c53 100644 --- a/src/main/scala/strawman/collection/Factories.scala +++ b/src/main/scala/strawman/collection/Factories.scala @@ -18,7 +18,7 @@ trait IterableFactory[+CC[_]] { def fromIterable[E](it: Iterable[E]): CC[E] - def empty[A]: CC[A] = fromIterable(View.Empty) + def empty[A]: CC[A] def apply[A](xs: A*): CC[A] = fromIterable(View.Elems(xs: _*)) diff --git a/src/main/scala/strawman/collection/View.scala b/src/main/scala/strawman/collection/View.scala index d98fa8928f..24d2508512 100644 --- a/src/main/scala/strawman/collection/View.scala +++ b/src/main/scala/strawman/collection/View.scala @@ -28,7 +28,7 @@ object View extends IterableFactory[View] { case _ => View.fromIterator(it.iterator()) } - override def empty[A]: View[A] = Empty + def empty[A]: View[A] = Empty override def apply[A](xs: A*): View[A] = Elems(xs: _*) /** The empty view */ diff --git a/src/main/scala/strawman/collection/immutable/HashSet.scala b/src/main/scala/strawman/collection/immutable/HashSet.scala index f7effc8d27..a207775d5c 100644 --- a/src/main/scala/strawman/collection/immutable/HashSet.scala +++ b/src/main/scala/strawman/collection/immutable/HashSet.scala @@ -60,7 +60,7 @@ object HashSet extends IterableFactory[HashSet] { case _ => empty ++ it } - override def empty[A]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]] + def empty[A]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]] private object EmptyHashSet extends HashSet[Any] { diff --git a/src/main/scala/strawman/collection/immutable/LazyList.scala b/src/main/scala/strawman/collection/immutable/LazyList.scala index 2d55d81ee4..68e1aed52e 100644 --- a/src/main/scala/strawman/collection/immutable/LazyList.scala +++ b/src/main/scala/strawman/collection/immutable/LazyList.scala @@ -67,5 +67,5 @@ object LazyList extends IterableFactory[LazyList] { def newBuilder[A]: Builder[A, LazyList[A]] = ??? - override def empty[A]: LazyList[A] = new LazyList[A](None) + def empty[A]: LazyList[A] = new LazyList[A](None) } diff --git a/src/main/scala/strawman/collection/immutable/List.scala b/src/main/scala/strawman/collection/immutable/List.scala index bcde5950da..cbe5e9912d 100644 --- a/src/main/scala/strawman/collection/immutable/List.scala +++ b/src/main/scala/strawman/collection/immutable/List.scala @@ -64,5 +64,5 @@ object List extends IterableFactory[List] { def newBuilder[A]: Builder[A, List[A]] = new ListBuffer[A].mapResult(_.toList) - override def empty[A <: Any]: List[A] = Nil + def empty[A]: List[A] = Nil } diff --git a/src/main/scala/strawman/collection/immutable/ListSet.scala b/src/main/scala/strawman/collection/immutable/ListSet.scala index a0d1ad67ce..41e1d294ba 100644 --- a/src/main/scala/strawman/collection/immutable/ListSet.scala +++ b/src/main/scala/strawman/collection/immutable/ListSet.scala @@ -122,7 +122,7 @@ object ListSet extends IterableFactory[ListSet] { private object EmptyListSet extends ListSet[Any] private[collection] def emptyInstance: ListSet[Any] = EmptyListSet - override def empty[A]: ListSet[A] = EmptyListSet.asInstanceOf[ListSet[A]] + def empty[A]: ListSet[A] = EmptyListSet.asInstanceOf[ListSet[A]] } diff --git a/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala b/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala index e800b37132..a25c4f287f 100644 --- a/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala +++ b/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala @@ -138,7 +138,7 @@ object ArrayBuffer extends IterableFactory[ArrayBuffer] { def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A]() - override def empty[A <: Any]: ArrayBuffer[A] = new ArrayBuffer[A]() + def empty[A <: Any]: ArrayBuffer[A] = new ArrayBuffer[A]() } class ArrayBufferView[A](val array: Array[AnyRef], val length: Int) extends IndexedView[A] { diff --git a/src/main/scala/strawman/collection/mutable/HashSet.scala b/src/main/scala/strawman/collection/mutable/HashSet.scala index 507cda3471..90053841d3 100644 --- a/src/main/scala/strawman/collection/mutable/HashSet.scala +++ b/src/main/scala/strawman/collection/mutable/HashSet.scala @@ -79,5 +79,5 @@ object HashSet extends IterableFactory[HashSet] { def fromIterable[B](it: strawman.collection.Iterable[B]): HashSet[B] = Growable.fromIterable(empty[B], it) - override def empty[A]: HashSet[A] = new HashSet[A] + def empty[A]: HashSet[A] = new HashSet[A] } diff --git a/src/main/scala/strawman/collection/mutable/ListBuffer.scala b/src/main/scala/strawman/collection/mutable/ListBuffer.scala index 0d240618d2..1a9bca059d 100644 --- a/src/main/scala/strawman/collection/mutable/ListBuffer.scala +++ b/src/main/scala/strawman/collection/mutable/ListBuffer.scala @@ -206,5 +206,5 @@ object ListBuffer extends IterableFactory[ListBuffer] { def newBuilder[A]: Builder[A, ListBuffer[A]] = new ListBuffer[A] - override def empty[A]: ListBuffer[A] = new ListBuffer[A] + def empty[A]: ListBuffer[A] = new ListBuffer[A] } From b0c61ac93443a95426f8484ac7d1169350fc098c Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 24 May 2017 10:35:44 +0200 Subject: [PATCH 5/8] =?UTF-8?q?Use=20=E2=80=9Csorted=E2=80=9D=20everywhere?= =?UTF-8?q?,=20for=20consistency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scala/strawman/collection/Factories.scala | 34 +++++++++---------- .../scala/strawman/collection/SortedMap.scala | 12 +++---- .../scala/strawman/collection/SortedSet.scala | 10 +++--- .../collection/immutable/BitSet.scala | 2 +- .../collection/immutable/SortedSet.scala | 2 +- .../collection/immutable/TreeMap.scala | 12 +++---- .../collection/immutable/TreeSet.scala | 10 +++--- .../strawman/collection/mutable/BitSet.scala | 4 +-- .../collection/mutable/SortedSet.scala | 2 +- .../strawman/collection/mutable/TreeMap.scala | 10 +++--- .../strawman/collection/mutable/TreeSet.scala | 10 +++--- 11 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/main/scala/strawman/collection/Factories.scala b/src/main/scala/strawman/collection/Factories.scala index f4d5f51c53..f5056944b1 100644 --- a/src/main/scala/strawman/collection/Factories.scala +++ b/src/main/scala/strawman/collection/Factories.scala @@ -74,54 +74,54 @@ object MapFactory { } /** Base trait for companion objects of collections that require an implicit evidence */ -trait OrderedIterableFactory[+CC[_]] { +trait SortedIterableFactory[+CC[_]] { - def orderedFromIterable[E : Ordering](it: Iterable[E]): CC[E] + def sortedFromIterable[E : Ordering](it: Iterable[E]): CC[E] def empty[A : Ordering]: CC[A] - def apply[A : Ordering](xs: A*): CC[A] = orderedFromIterable(View.Elems(xs: _*)) + def apply[A : Ordering](xs: A*): CC[A] = sortedFromIterable(View.Elems(xs: _*)) - def fill[A : Ordering](n: Int)(elem: => A): CC[A] = orderedFromIterable(View.Fill(n)(elem)) + def fill[A : Ordering](n: Int)(elem: => A): CC[A] = sortedFromIterable(View.Fill(n)(elem)) } -object OrderedIterableFactory { +object SortedIterableFactory { import scala.language.implicitConversions - implicit def toSpecific[A: Ordering, CC[_]](factory: OrderedIterableFactory[CC]): FromSpecificIterable[A, CC[A]] = + implicit def toSpecific[A: Ordering, CC[_]](factory: SortedIterableFactory[CC]): FromSpecificIterable[A, CC[A]] = new FromSpecificIterable[A, CC[A]] { - def fromSpecificIterable(it: Iterable[A]): CC[A] = factory.orderedFromIterable[A](it) + def fromSpecificIterable(it: Iterable[A]): CC[A] = factory.sortedFromIterable[A](it) } - class Delegate[CC[_]](delegate: OrderedIterableFactory[CC]) extends OrderedIterableFactory[CC] { + class Delegate[CC[_]](delegate: SortedIterableFactory[CC]) extends SortedIterableFactory[CC] { def empty[A : Ordering]: CC[A] = delegate.empty - def orderedFromIterable[E : Ordering](it: Iterable[E]): CC[E] = delegate.orderedFromIterable(it) + def sortedFromIterable[E : Ordering](it: Iterable[E]): CC[E] = delegate.sortedFromIterable(it) } } /** Factory methods for collections of kind `* −> * -> *` which require an implicit evidence value for the key type */ -trait OrderedMapFactory[+CC[X, Y]] { +trait SortedMapFactory[+CC[X, Y]] { def empty[K : Ordering, V]: CC[K, V] - def orderedFromIterable[K : Ordering, V](it: Iterable[(K, V)]): CC[K, V] + def sortedFromIterable[K : Ordering, V](it: Iterable[(K, V)]): CC[K, V] def apply[K : Ordering, V](elems: (K, V)*): CC[K, V] = - orderedFromIterable(elems.toStrawman) + sortedFromIterable(elems.toStrawman) } -object OrderedMapFactory { +object SortedMapFactory { import scala.language.implicitConversions - implicit def toSpecific[K : Ordering, V, CC[_, _]](factory: OrderedMapFactory[CC]): FromSpecificIterable[(K, V), CC[K, V]] = + implicit def toSpecific[K : Ordering, V, CC[_, _]](factory: SortedMapFactory[CC]): FromSpecificIterable[(K, V), CC[K, V]] = new FromSpecificIterable[(K, V), CC[K, V]] { - def fromSpecificIterable(it: Iterable[(K, V)]): CC[K, V] = factory.orderedFromIterable(it) + def fromSpecificIterable(it: Iterable[(K, V)]): CC[K, V] = factory.sortedFromIterable(it) } - class Delegate[CC[_, _]](delegate: OrderedMapFactory[CC]) extends OrderedMapFactory[CC] { + class Delegate[CC[_, _]](delegate: SortedMapFactory[CC]) extends SortedMapFactory[CC] { def empty[K: Ordering, V]: CC[K, V] = delegate.empty[K, V] - def orderedFromIterable[K: Ordering, V](it: Iterable[(K, V)]): CC[K, V] = delegate.orderedFromIterable(it) + def sortedFromIterable[K: Ordering, V](it: Iterable[(K, V)]): CC[K, V] = delegate.sortedFromIterable(it) } } diff --git a/src/main/scala/strawman/collection/SortedMap.scala b/src/main/scala/strawman/collection/SortedMap.scala index 18e2e92074..ef3e20d500 100644 --- a/src/main/scala/strawman/collection/SortedMap.scala +++ b/src/main/scala/strawman/collection/SortedMap.scala @@ -14,17 +14,17 @@ trait SortedMapOps[K, +V, +CC[X, Y] <: SortedMap[X, Y] with SortedMapOps[X, Y, C extends MapOps[K, V, Map, C] with SortedOps[K, C] { - protected[this] def orderedMapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] + protected[this] def sortedMapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] def firstKey: K = head._1 def lastKey: K = last._1 // And finally, we add new overloads taking an ordering def map[K2, V2](f: ((K, V)) => (K2, V2))(implicit ordering: Ordering[K2]): CC[K2, V2] = - orderedMapFromIterable(View.Map[(K, V), (K2, V2)](coll, f)) + sortedMapFromIterable(View.Map[(K, V), (K2, V2)](coll, f)) def flatMap[K2, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] = - orderedMapFromIterable(View.FlatMap(coll, f)) + sortedMapFromIterable(View.FlatMap(coll, f)) /** Returns a new $coll containing the elements from the left hand operand followed by the elements from the * right hand operand. The element type of the $coll is the most specific superclass encompassing @@ -36,16 +36,16 @@ trait SortedMapOps[K, +V, +CC[X, Y] <: SortedMap[X, Y] with SortedMapOps[X, Y, C * @return a new collection of type `CC[K2, V2]` which contains all elements * of this $coll followed by all elements of `xs`. */ - def concat[K2 >: K, V2 >: V](xs: IterableOnce[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] = orderedMapFromIterable(View.Concat(coll, xs)) + def concat[K2 >: K, V2 >: V](xs: IterableOnce[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] = sortedMapFromIterable(View.Concat(coll, xs)) /** Alias for `concat` */ @`inline` final def ++ [K2 >: K, V2 >: V](xs: IterableOnce[(K2, V2)])(implicit ordering: Ordering[K2]): CC[K2, V2] = concat(xs) // We override these methods to fix their return type (which would be `Map` otherwise) - override def concat[V2 >: V](xs: collection.Iterable[(K, V2)]): CC[K, V2] = orderedMapFromIterable(View.Concat(coll, xs)) + override def concat[V2 >: V](xs: collection.Iterable[(K, V2)]): CC[K, V2] = sortedMapFromIterable(View.Concat(coll, xs)) override def ++ [V2 >: V](xs: collection.Iterable[(K, V2)]): CC[K, V2] = concat(xs) // TODO Also override mapValues } -object SortedMap extends OrderedMapFactory.Delegate[SortedMap](TreeMap) +object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) diff --git a/src/main/scala/strawman/collection/SortedSet.scala b/src/main/scala/strawman/collection/SortedSet.scala index cfd796daaa..e7e41cd007 100644 --- a/src/main/scala/strawman/collection/SortedSet.scala +++ b/src/main/scala/strawman/collection/SortedSet.scala @@ -11,19 +11,19 @@ trait SortedSetOps[A, +CC[X], +C <: SortedSet[A]] extends SetOps[A, Set, C] with SortedOps[A, C] { - protected[this] def orderedFromIterable[B: Ordering](it: Iterable[B]): CC[B] + protected[this] def sortedFromIterable[B: Ordering](it: Iterable[B]): CC[B] def firstKey: A = head def lastKey: A = last /** Map */ - def map[B : Ordering](f: A => B): CC[B] = orderedFromIterable(View.Map(coll, f)) + def map[B : Ordering](f: A => B): CC[B] = sortedFromIterable(View.Map(coll, f)) /** Flatmap */ - def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = orderedFromIterable(View.FlatMap(coll, f)) + def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedFromIterable(View.FlatMap(coll, f)) /** Zip. Interesting because it requires to align to source collections. */ - def zip[B](xs: IterableOnce[B])(implicit ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = orderedFromIterable(View.Zip(coll, xs)) + def zip[B](xs: IterableOnce[B])(implicit ev: Ordering[(A @uncheckedVariance, B)]): CC[(A @uncheckedVariance, B)] = sortedFromIterable(View.Zip(coll, xs)) // sound bcs of VarianceNote def collect[B: Ordering](pf: scala.PartialFunction[A, B]): CC[B] = flatMap(a => @@ -32,4 +32,4 @@ trait SortedSetOps[A, +CC[X], +C <: SortedSet[A]] ) } -object SortedSet extends OrderedIterableFactory.Delegate[SortedSet](immutable.SortedSet) +object SortedSet extends SortedIterableFactory.Delegate[SortedSet](immutable.SortedSet) diff --git a/src/main/scala/strawman/collection/immutable/BitSet.scala b/src/main/scala/strawman/collection/immutable/BitSet.scala index ff2a078696..b704e69bc4 100644 --- a/src/main/scala/strawman/collection/immutable/BitSet.scala +++ b/src/main/scala/strawman/collection/immutable/BitSet.scala @@ -29,7 +29,7 @@ sealed abstract class BitSet def iterableFactory = Set protected[this] def fromSpecificIterable(coll: collection.Iterable[Int]): BitSet = BitSet.fromSpecificIterable(coll) - protected[this] def orderedFromIterable[B : Ordering](it: collection.Iterable[B]): SortedSet[B] = SortedSet.orderedFromIterable(it) + protected[this] def sortedFromIterable[B : Ordering](it: collection.Iterable[B]): SortedSet[B] = SortedSet.sortedFromIterable(it) protected[collection] def fromBitMaskNoCopy(elems: Array[Long]): BitSet = BitSet.fromBitMaskNoCopy(elems) diff --git a/src/main/scala/strawman/collection/immutable/SortedSet.scala b/src/main/scala/strawman/collection/immutable/SortedSet.scala index 1451e342fb..bff9e4d616 100644 --- a/src/main/scala/strawman/collection/immutable/SortedSet.scala +++ b/src/main/scala/strawman/collection/immutable/SortedSet.scala @@ -17,4 +17,4 @@ trait SortedSetOps[A, extends SetOps[A, Set, C] with collection.SortedSetOps[A, CC, C] -object SortedSet extends OrderedIterableFactory.Delegate[SortedSet](TreeSet) +object SortedSet extends SortedIterableFactory.Delegate[SortedSet](TreeSet) diff --git a/src/main/scala/strawman/collection/immutable/TreeMap.scala b/src/main/scala/strawman/collection/immutable/TreeMap.scala index 06ca234d36..b22d1d76e8 100644 --- a/src/main/scala/strawman/collection/immutable/TreeMap.scala +++ b/src/main/scala/strawman/collection/immutable/TreeMap.scala @@ -2,7 +2,7 @@ package strawman package collection package immutable -import strawman.collection.OrderedMapFactory +import strawman.collection.SortedMapFactory import strawman.collection.immutable.{RedBlackTree => RB} import strawman.collection.mutable.Builder @@ -39,10 +39,10 @@ final class TreeMap[K, +V] private (tree: RB.Tree[K, V])(implicit val ordering: def iterableFactory = List protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)]): TreeMap[K, V] = - TreeMap.orderedFromIterable(coll) + TreeMap.sortedFromIterable(coll) - protected[this] def orderedMapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): TreeMap[K2, V2] = - TreeMap.orderedFromIterable(it) + protected[this] def sortedMapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): TreeMap[K2, V2] = + TreeMap.sortedFromIterable(it) def iterator(): collection.Iterator[(K, V)] = RB.iterator(tree) @@ -100,11 +100,11 @@ final class TreeMap[K, +V] private (tree: RB.Tree[K, V])(implicit val ordering: * @define Coll immutable.TreeMap * @define coll immutable tree map */ -object TreeMap extends OrderedMapFactory[TreeMap] { +object TreeMap extends SortedMapFactory[TreeMap] { def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap() - def orderedFromIterable[K : Ordering, V](it: collection.Iterable[(K, V)]): TreeMap[K, V] = + def sortedFromIterable[K : Ordering, V](it: collection.Iterable[(K, V)]): TreeMap[K, V] = it match { case tm: TreeMap[K, V] => tm case _ => empty[K, V] ++ it diff --git a/src/main/scala/strawman/collection/immutable/TreeSet.scala b/src/main/scala/strawman/collection/immutable/TreeSet.scala index 02cc5d6f31..f21ce1d508 100644 --- a/src/main/scala/strawman/collection/immutable/TreeSet.scala +++ b/src/main/scala/strawman/collection/immutable/TreeSet.scala @@ -64,10 +64,10 @@ final class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: O def iterableFactory = Set protected[this] def fromSpecificIterable(coll: strawman.collection.Iterable[A]): TreeSet[A] = - TreeSet.orderedFromIterable(coll) + TreeSet.sortedFromIterable(coll) - protected[this] def orderedFromIterable[B : Ordering](coll: strawman.collection.Iterable[B]): TreeSet[B] = - TreeSet.orderedFromIterable(coll) + protected[this] def sortedFromIterable[B : Ordering](coll: strawman.collection.Iterable[B]): TreeSet[B] = + TreeSet.sortedFromIterable(coll) def unordered: Set[A] = this @@ -103,11 +103,11 @@ final class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: O else newSet(RB.delete(tree, elem)) } -object TreeSet extends OrderedIterableFactory[TreeSet] { +object TreeSet extends SortedIterableFactory[TreeSet] { def empty[A: Ordering]: TreeSet[A] = new TreeSet[A] - def orderedFromIterable[E: Ordering](it: strawman.collection.Iterable[E]): TreeSet[E] = + def sortedFromIterable[E: Ordering](it: strawman.collection.Iterable[E]): TreeSet[E] = it match { case ts: TreeSet[E] => ts case _ => empty[E] ++ it diff --git a/src/main/scala/strawman/collection/mutable/BitSet.scala b/src/main/scala/strawman/collection/mutable/BitSet.scala index 7b5fbb6c2b..335a7e92b4 100644 --- a/src/main/scala/strawman/collection/mutable/BitSet.scala +++ b/src/main/scala/strawman/collection/mutable/BitSet.scala @@ -36,8 +36,8 @@ class BitSet(protected[collection] final var elems: Array[Long]) def iterableFactory = Set - protected[this] def orderedFromIterable[B : Ordering](it: collection.Iterable[B]): collection.mutable.SortedSet[B] = - collection.mutable.SortedSet.orderedFromIterable(it) + protected[this] def sortedFromIterable[B : Ordering](it: collection.Iterable[B]): collection.mutable.SortedSet[B] = + collection.mutable.SortedSet.sortedFromIterable(it) protected[this] def fromSpecificIterable(coll: collection.Iterable[Int]): BitSet = BitSet.fromSpecificIterable(coll) diff --git a/src/main/scala/strawman/collection/mutable/SortedSet.scala b/src/main/scala/strawman/collection/mutable/SortedSet.scala index 7baf8e3e4d..171d99dbd7 100644 --- a/src/main/scala/strawman/collection/mutable/SortedSet.scala +++ b/src/main/scala/strawman/collection/mutable/SortedSet.scala @@ -17,4 +17,4 @@ trait SortedSetOps[A, +CC[X], +C <: SortedSet[A]] with collection.SortedSetOps[A, CC, C] object SortedSet - extends OrderedIterableFactory.Delegate[SortedSet](TreeSet) + extends SortedIterableFactory.Delegate[SortedSet](TreeSet) diff --git a/src/main/scala/strawman/collection/mutable/TreeMap.scala b/src/main/scala/strawman/collection/mutable/TreeMap.scala index 0c8a9c8a33..2d4d68be28 100644 --- a/src/main/scala/strawman/collection/mutable/TreeMap.scala +++ b/src/main/scala/strawman/collection/mutable/TreeMap.scala @@ -1,7 +1,7 @@ package strawman package collection.mutable -import collection.{Iterator, OrderedMapFactory} +import collection.{Iterator, SortedMapFactory} import collection.mutable.{RedBlackTree => RB} import scala.{Boolean, Int, None, Option, Ordering, SerialVersionUID, Serializable, Some, Unit} @@ -34,9 +34,9 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: */ def this()(implicit ord: Ordering[K]) = this(RB.Tree.empty)(ord) - protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)]): TreeMap[K, V] = TreeMap.orderedFromIterable(coll) + protected[this] def fromSpecificIterable(coll: collection.Iterable[(K, V)]): TreeMap[K, V] = TreeMap.sortedFromIterable(coll) - protected[this] def orderedMapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): TreeMap[K2, V2] = TreeMap.orderedFromIterable(it) + protected[this] def sortedMapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)])(implicit ordering: Ordering[K2]): TreeMap[K2, V2] = TreeMap.sortedFromIterable(it) def iterator(): Iterator[(K, V)] = RB.iterator(tree) @@ -172,9 +172,9 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: * @define Coll mutable.TreeMap * @define coll mutable tree map */ -object TreeMap extends OrderedMapFactory[TreeMap] { +object TreeMap extends SortedMapFactory[TreeMap] { - def orderedFromIterable[K : Ordering, V](it: collection.Iterable[(K, V)]): TreeMap[K, V] = + def sortedFromIterable[K : Ordering, V](it: collection.Iterable[(K, V)]): TreeMap[K, V] = Growable.fromIterable(empty[K, V], it) def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap[K, V]() diff --git a/src/main/scala/strawman/collection/mutable/TreeSet.scala b/src/main/scala/strawman/collection/mutable/TreeSet.scala index 3fe17a7aeb..305837ea93 100644 --- a/src/main/scala/strawman/collection/mutable/TreeSet.scala +++ b/src/main/scala/strawman/collection/mutable/TreeSet.scala @@ -1,7 +1,7 @@ package strawman package collection.mutable -import collection.OrderedIterableFactory +import collection.SortedIterableFactory import collection.mutable.{RedBlackTree => RB} import scala.{Boolean, Int, None, Null, NullPointerException, Option, Ordering, Serializable, SerialVersionUID, Some, Unit} @@ -39,9 +39,9 @@ sealed class TreeSet[A] private (tree: RB.Tree[A, Null])(implicit val ordering: def iterator(): collection.Iterator[A] = RB.keysIterator(tree) - protected[this] def orderedFromIterable[B : Ordering](it: collection.Iterable[B]): TreeSet[B] = TreeSet.orderedFromIterable(it) + protected[this] def sortedFromIterable[B : Ordering](it: collection.Iterable[B]): TreeSet[B] = TreeSet.sortedFromIterable(it) - protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): TreeSet[A] = TreeSet.orderedFromIterable(coll) + protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): TreeSet[A] = TreeSet.sortedFromIterable(coll) def iterableFactory = Set @@ -175,10 +175,10 @@ sealed class TreeSet[A] private (tree: RB.Tree[A, Null])(implicit val ordering: * @author Lucien Pereira * */ -object TreeSet extends OrderedIterableFactory[TreeSet] { +object TreeSet extends SortedIterableFactory[TreeSet] { def empty[A : Ordering]: TreeSet[A] = new TreeSet[A]() - def orderedFromIterable[E : Ordering](it: collection.Iterable[E]): TreeSet[E] = Growable.fromIterable(empty[E], it) + def sortedFromIterable[E : Ordering](it: collection.Iterable[E]): TreeSet[E] = Growable.fromIterable(empty[E], it) } From c8434cc0a4e48f7d63a2c598e3096d3efcd8c33d Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 24 May 2017 14:09:29 +0200 Subject: [PATCH 6/8] Introduce factories with builders. Optimize optionSequence (in TraverseTest) when the underlying IterableFactory happens to be an IterableFactoryWithBuilder --- .../scala/strawman/collection/Factories.scala | 8 +- .../scala/strawman/collection/SortedSet.scala | 2 + .../collection/immutable/LazyList.scala | 2 - .../strawman/collection/immutable/List.scala | 4 +- .../collection/immutable/SortedMap.scala | 9 +++ .../collection/mutable/ArrayBuffer.scala | 6 +- .../strawman/collection/mutable/HashSet.scala | 7 +- .../collection/mutable/ListBuffer.scala | 4 +- .../collection/test/TraverseTest.scala | 73 ++++++------------- 9 files changed, 53 insertions(+), 62 deletions(-) diff --git a/src/main/scala/strawman/collection/Factories.scala b/src/main/scala/strawman/collection/Factories.scala index f5056944b1..24fdce5672 100644 --- a/src/main/scala/strawman/collection/Factories.scala +++ b/src/main/scala/strawman/collection/Factories.scala @@ -1,7 +1,9 @@ package strawman package collection -import scala.{Any, Int, Ordering, Nothing} +import strawman.collection.mutable.Builder + +import scala.{Any, Int, Nothing, Ordering} import scala.annotation.unchecked.uncheckedVariance /** @@ -26,6 +28,10 @@ trait IterableFactory[+CC[_]] { } +trait IterableFactoryWithBuilder[+CC[_]] extends IterableFactory[CC] { + def newBuilder[A](): Builder[A, CC[A]] +} + object IterableFactory { import scala.language.implicitConversions diff --git a/src/main/scala/strawman/collection/SortedSet.scala b/src/main/scala/strawman/collection/SortedSet.scala index e7e41cd007..f0e6289cbf 100644 --- a/src/main/scala/strawman/collection/SortedSet.scala +++ b/src/main/scala/strawman/collection/SortedSet.scala @@ -13,6 +13,8 @@ trait SortedSetOps[A, +CC[X], +C <: SortedSet[A]] protected[this] def sortedFromIterable[B: Ordering](it: Iterable[B]): CC[B] + def iterableFactory: IterableFactory[Set] + def firstKey: A = head def lastKey: A = last diff --git a/src/main/scala/strawman/collection/immutable/LazyList.scala b/src/main/scala/strawman/collection/immutable/LazyList.scala index 68e1aed52e..b385c0b8ea 100644 --- a/src/main/scala/strawman/collection/immutable/LazyList.scala +++ b/src/main/scala/strawman/collection/immutable/LazyList.scala @@ -65,7 +65,5 @@ object LazyList extends IterableFactory[LazyList] { def fromIterator[A](it: Iterator[A]): LazyList[A] = new LazyList(if (it.hasNext) Some(it.next(), fromIterator(it)) else None) - def newBuilder[A]: Builder[A, LazyList[A]] = ??? - def empty[A]: LazyList[A] = new LazyList[A](None) } diff --git a/src/main/scala/strawman/collection/immutable/List.scala b/src/main/scala/strawman/collection/immutable/List.scala index cbe5e9912d..d290c638c7 100644 --- a/src/main/scala/strawman/collection/immutable/List.scala +++ b/src/main/scala/strawman/collection/immutable/List.scala @@ -55,14 +55,14 @@ case object Nil extends List[Nothing] { override def tail: Nothing = throw new UnsupportedOperationException("tail of empty list") } -object List extends IterableFactory[List] { +object List extends IterableFactoryWithBuilder[List] { def fromIterable[B](coll: collection.Iterable[B]): List[B] = coll match { case coll: List[B] => coll case _ => ListBuffer.fromIterable(coll).toList } - def newBuilder[A]: Builder[A, List[A]] = new ListBuffer[A].mapResult(_.toList) + def newBuilder[A](): Builder[A, List[A]] = new ListBuffer[A].mapResult(_.toList) def empty[A]: List[A] = Nil } diff --git a/src/main/scala/strawman/collection/immutable/SortedMap.scala b/src/main/scala/strawman/collection/immutable/SortedMap.scala index 0e757e8609..8643d7ae38 100644 --- a/src/main/scala/strawman/collection/immutable/SortedMap.scala +++ b/src/main/scala/strawman/collection/immutable/SortedMap.scala @@ -13,6 +13,8 @@ trait SortedMapOps[K, +V, +CC[X, +Y] <: SortedMap[X, Y] with SortedMapOps[X, Y, extends MapOps[K, V, Map, C] with collection.SortedMapOps[K, V, CC, C] { + protected[this] def coll: CC[K, V] + protected def mapFromIterable[K2, V2](it: collection.Iterable[(K2, V2)]): Map[K2, V2] = Map.fromIterable(it) @@ -20,5 +22,12 @@ trait SortedMapOps[K, +V, +CC[X, +Y] <: SortedMap[X, Y] with SortedMapOps[X, Y, def updated[V1 >: V](key: K, value: V1): CC[K, V1] override def + [V1 >: V](kv: (K, V1)): CC[K, V1] = updated(kv._1, kv._2) + override def concat[V2 >: V](xs: collection.Iterable[(K, V2)]): CC[K, V2] = { + var result: CC[K, V2] = coll + val it = xs.iterator() + while (it.hasNext) result = result + it.next() + result + } + } diff --git a/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala b/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala index a25c4f287f..019e37dcc9 100644 --- a/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala +++ b/src/main/scala/strawman/collection/mutable/ArrayBuffer.scala @@ -124,7 +124,7 @@ class ArrayBuffer[A] private (initElems: Array[AnyRef], initLength: Int) override def className = "ArrayBuffer" } -object ArrayBuffer extends IterableFactory[ArrayBuffer] { +object ArrayBuffer extends IterableFactoryWithBuilder[ArrayBuffer] { /** Avoid reallocation of buffer if length is known. */ def fromIterable[B](coll: collection.Iterable[B]): ArrayBuffer[B] = @@ -136,9 +136,9 @@ object ArrayBuffer extends IterableFactory[ArrayBuffer] { } else new ArrayBuffer[B] ++= coll - def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A]() + def newBuilder[A](): Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A]() - def empty[A <: Any]: ArrayBuffer[A] = new ArrayBuffer[A]() + def empty[A]: ArrayBuffer[A] = new ArrayBuffer[A]() } class ArrayBufferView[A](val array: Array[AnyRef], val length: Int) extends IndexedView[A] { diff --git a/src/main/scala/strawman/collection/mutable/HashSet.scala b/src/main/scala/strawman/collection/mutable/HashSet.scala index 90053841d3..8d79668a80 100644 --- a/src/main/scala/strawman/collection/mutable/HashSet.scala +++ b/src/main/scala/strawman/collection/mutable/HashSet.scala @@ -35,7 +35,7 @@ final class HashSet[A](contents: FlatHashTable.Contents[A]) protected[this] def fromSpecificIterable(coll: collection.Iterable[A]): HashSet[A] = fromIterable(coll) - protected[this] def newBuilder: Builder[A, HashSet[A]] = new GrowableBuilder[A, HashSet[A]](empty) + protected[this] def newBuilder: Builder[A, HashSet[A]] = HashSet.newBuilder[A]() def add(elem: A): this.type = { table.addElem(elem) @@ -75,9 +75,12 @@ final class HashSet[A](contents: FlatHashTable.Contents[A]) } -object HashSet extends IterableFactory[HashSet] { +object HashSet extends IterableFactoryWithBuilder[HashSet] { def fromIterable[B](it: strawman.collection.Iterable[B]): HashSet[B] = Growable.fromIterable(empty[B], it) def empty[A]: HashSet[A] = new HashSet[A] + + def newBuilder[A](): Builder[A, HashSet[A]] = new GrowableBuilder[A, HashSet[A]](empty) + } diff --git a/src/main/scala/strawman/collection/mutable/ListBuffer.scala b/src/main/scala/strawman/collection/mutable/ListBuffer.scala index 1a9bca059d..7db351d102 100644 --- a/src/main/scala/strawman/collection/mutable/ListBuffer.scala +++ b/src/main/scala/strawman/collection/mutable/ListBuffer.scala @@ -200,11 +200,11 @@ class ListBuffer[A] override def className = "ListBuffer" } -object ListBuffer extends IterableFactory[ListBuffer] { +object ListBuffer extends IterableFactoryWithBuilder[ListBuffer] { def fromIterable[A](coll: collection.Iterable[A]): ListBuffer[A] = new ListBuffer[A] ++= coll - def newBuilder[A]: Builder[A, ListBuffer[A]] = new ListBuffer[A] + def newBuilder[A](): Builder[A, ListBuffer[A]] = new ListBuffer[A] def empty[A]: ListBuffer[A] = new ListBuffer[A] } diff --git a/src/test/scala/strawman/collection/test/TraverseTest.scala b/src/test/scala/strawman/collection/test/TraverseTest.scala index 936b39774b..00970cd8be 100644 --- a/src/test/scala/strawman/collection/test/TraverseTest.scala +++ b/src/test/scala/strawman/collection/test/TraverseTest.scala @@ -4,7 +4,7 @@ package collection.test import org.junit.Test import strawman.collection.Iterable -import strawman.collection.mutable.{Builder, ArrayBuffer} +import strawman.collection.mutable.{ArrayBuffer, Builder, Growable} import strawman.collection._ import scala.{Any, Either, Int, Left, None, Option, Right, Some, Unit} @@ -14,67 +14,40 @@ import java.lang.String class TraverseTest { - // You can either overload methods for PolyBuildable and OrderedPolyBuildable (if you want to support ordered collection types) - def optionSequence1[C[X] <: Iterable[X] with IterableOps[X, C, _], A](xs: C[Option[A]]): Option[C[A]] = - xs.foldLeft[Option[ArrayBuffer[A]]](Some(new ArrayBuffer[A])) { (bo, xo) => + def optionSequence[CC[X] <: Iterable[X] with IterableOps[X, CC, _], A](xs: CC[Option[A]]): Option[CC[A]] = { + def folder[F[X] <: Growable[X]]: (Option[F[A]], Option[A]) => Option[F[A]] = { (bo, xo) => (bo, xo) match { case (Some(builder), Some(a)) => Some(builder += a) case _ => None } - }.map(_.to(xs.iterableFactory)) - -// def optionSequence1[CC[_], A](xs: OrderedPolyBuildable[Option[A], CC] with Iterable[Option[A]])(implicit ev: Ordering[A]): Option[CC[A]] = -// xs.foldLeft[Option[Builder[A, CC[A]]]](Some(xs.newOrderedBuilder)) { -// case (Some(builder), Some(a)) => Some(builder += a) -// case _ => None -// }.map(_.result) -// -// // ...or use BuildFrom to abstract over both and also allow building arbitrary collection types -// def optionSequence[CC[X] <: Iterable[X], A](xs: CC[Option[A]])(implicit bf: BuildFrom[CC[Option[A]], A]): Option[bf.To] = -// xs.foldLeft[Option[Builder[A, bf.To]]](Some(bf.newBuilder(xs))) { -// case (Some(builder), Some(a)) => Some(builder += a) -// case _ => None -// }.map(_.result) -// -// def eitherSequence[C[X] <: Iterable[X], A, B](xs: C[Either[A, B]])(implicit bf: BuildFrom[xs.type, B]): Either[A, bf.To] = -// xs.foldLeft[Either[A, Builder[B, bf.To]]](Right(bf.newBuilder(xs))) { -// case (Right(builder), Right(b)) => Right(builder += b) -// case (Left(a) , _) => Left(a) -// case (_ , Left(a)) => Left(a) -// }.right.map(_.result) + } + val factory = xs.iterableFactory + factory match { + case iterableBuilder: IterableFactoryWithBuilder[CC] => + xs.foldLeft[Option[Builder[A, CC[A]]]]( + Some(iterableBuilder.newBuilder[A]()) + )( + folder[({ type l[X] = Builder[X, CC[X]] })#l] + ).map(_.result) + case _ => + xs.foldLeft[Option[ArrayBuffer[A]]](Some(new ArrayBuffer[A]))(folder).map(_.to(xs.iterableFactory)) + } + } @Test def optionSequence1Test: Unit = { val xs1 = immutable.List(Some(1), None, Some(2)) - val o1 = optionSequence1(xs1) + val o1 = optionSequence(xs1) val o1t: Option[immutable.List[Int]] = o1 val xs2: immutable.Set[Option[String]] = immutable.TreeSet(Some("foo"), Some("bar"), None) - val o2 = optionSequence1(xs2) + val o2 = optionSequence(xs2) val o2t: Option[immutable.Set[String]] = o2 - } -// def optionSequenceTest: Unit = { -// val xs1 = immutable.List(Some(1), None, Some(2)) -// val o1 = optionSequence(xs1) -// val o1t: Option[immutable.List[Int]] = o1 -// -// val xs2 = immutable.TreeSet(Some("foo"), Some("bar"), None) -// val o2 = optionSequence(xs2) -// val o2t: Option[immutable.TreeSet[String]] = o2 -// -// // Breakout-like use case from https://github.com/scala/scala/pull/5233: -// val xs4 = immutable.List[Option[(Int, String)]](Some((1 -> "a")), Some((2 -> "b"))) -// val o4 = optionSequence(xs4)(immutable.TreeMap) // same syntax as in `.to` -// val o4t: Option[immutable.TreeMap[Int, String]] = o4 -// } -// -// @Test -// def eitherSequenceTest: Unit = { -// val xs3 = mutable.ListBuffer(Right("foo"), Left(0), Right("bar")) -// val xs3t: mutable.ListBuffer[Either[Int, String]] = xs3 -// val e1 = eitherSequence(xs3) -// val e1t: Either[Int, mutable.ListBuffer[String]] = e1 -// } + val xs4 = immutable.List[Option[(Int, String)]](Some((1 -> "a")), Some((2 -> "b"))) + val o4 = optionSequence(xs4) + val o4t: Option[immutable.List[(Int, String)]] = o4 + val o5: Option[immutable.TreeMap[Int, String]] = o4.map(_.to(immutable.TreeMap)) + } } From 43d88f7321f943f00e7926b87a203114b69a1b22 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 24 May 2017 14:17:04 +0200 Subject: [PATCH 7/8] =?UTF-8?q?remove=20unnecessary=20=E2=80=9Coverride?= =?UTF-8?q?=E2=80=9D=20modifier?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/scala/strawman/collection/Factories.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/strawman/collection/Factories.scala b/src/main/scala/strawman/collection/Factories.scala index 24fdce5672..074a55c382 100644 --- a/src/main/scala/strawman/collection/Factories.scala +++ b/src/main/scala/strawman/collection/Factories.scala @@ -41,7 +41,7 @@ object IterableFactory { } class Delegate[CC[_]](delegate: IterableFactory[CC]) extends IterableFactory[CC] { - override def empty[A]: CC[A] = delegate.empty + def empty[A]: CC[A] = delegate.empty def fromIterable[E](it: Iterable[E]): CC[E] = delegate.fromIterable(it) } From 021f8742c31ebbee2915495bb8d91251da0b593f Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 24 May 2017 14:21:00 +0200 Subject: [PATCH 8/8] Remove unnecessary refinement --- src/main/scala/strawman/collection/SortedSet.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/scala/strawman/collection/SortedSet.scala b/src/main/scala/strawman/collection/SortedSet.scala index f0e6289cbf..e7e41cd007 100644 --- a/src/main/scala/strawman/collection/SortedSet.scala +++ b/src/main/scala/strawman/collection/SortedSet.scala @@ -13,8 +13,6 @@ trait SortedSetOps[A, +CC[X], +C <: SortedSet[A]] protected[this] def sortedFromIterable[B: Ordering](it: Iterable[B]): CC[B] - def iterableFactory: IterableFactory[Set] - def firstKey: A = head def lastKey: A = last