diff --git a/src/main/scala/strawman/collection/Factories.scala b/src/main/scala/strawman/collection/Factories.scala index 418d000d76..0e54cf5be2 100644 --- a/src/main/scala/strawman/collection/Factories.scala +++ b/src/main/scala/strawman/collection/Factories.scala @@ -24,42 +24,12 @@ trait BuildFrom[-From, -A, +C] extends Any { def newBuilder(from: From): Builder[A, C] } -object BuildFrom extends BuildFromLowPriority { - /** Build the source collection type from a MapOps */ - implicit def buildFromMapOps[CC[K, V] <: Map[K, V] with MapOps[K, V, CC, _], A, B, E, F]: BuildFrom[CC[A, B], (E, F), CC[E, F]] = new BuildFrom[CC[A, B], (E, F), CC[E, F]] { - //TODO: Reuse a prototype instance - def newBuilder(from: CC[A, B]): Builder[(E, F), CC[E, F]] = from.mapFactory.newBuilder[E, F]() - def fromSpecificIterable(from: CC[A, B])(it: Iterable[(E, F)]): CC[E, F] = from.mapFactory.fromIterable(it) - } - - /** Build the source collection type from a SortedMapOps */ - implicit def buildFromSortedMapOps[CC[K, V] <: SortedMap[K, V] with SortedMapOps[K, V, CC, _], A, B, E : Ordering, F]: BuildFrom[CC[A, B], (E, F), CC[E, F]] = new BuildFrom[CC[A, B], (E, F), CC[E, F]] { - def newBuilder(from: CC[A, B]): Builder[(E, F), CC[E, F]] = from.sortedMapFactory.newBuilder[E, F]() - def fromSpecificIterable(from: CC[A, B])(it: Iterable[(E, F)]): CC[E, F] = from.sortedMapFactory.fromSpecificIterable(it) - } -} - -trait BuildFromLowPriority { - /** Build the source collection type from an IterableOps */ - implicit def buildFromIterableOps[CC[X] <: Iterable[X] with IterableOps[X, CC, _], A, E]: BuildFrom[CC[A], E, CC[E]] = new BuildFrom[CC[A], E, CC[E]] { - //TODO: Reuse a prototype instance - def newBuilder(from: CC[A]): Builder[E, CC[E]] = from.iterableFactory.newBuilder[E]() - def fromSpecificIterable(from: CC[A])(it: Iterable[E]): CC[E] = from.iterableFactory.fromIterable(it) - } - - /** Build the source collection type from an Iterable with SortedOps */ - implicit def buildFromSortedOps[CC[X] <: Iterable[X] with SortedOps[X, CC, _], A, E : Ordering]: BuildFrom[CC[A], E, CC[E]] = new BuildFrom[CC[A], E, CC[E]] { - def newBuilder(from: CC[A]): Builder[E, CC[E]] = from.sortedIterableFactory.newBuilder[E]() - def fromSpecificIterable(from: CC[A])(it: Iterable[E]): CC[E] = from.sortedIterableFactory.fromSpecificIterable(it) - } -} - /** * Builds a collection of type `C` from elements of type `A` * @tparam A Type of elements (e.g. `Int`, `Boolean`, etc.) * @tparam C Type of collection (e.g. `List[Int]`, `TreeMap[Int, String]`, etc.) */ -trait FromSpecificIterable[-A, +C] extends Any with BuildFrom[Any, A, C] { +trait CanBuild[-A, +C] extends Any with BuildFrom[Any, A, C] { def fromSpecificIterable(from: Any)(it: Iterable[A]): C = fromSpecificIterable(it) def fromSpecificIterable(it: Iterable[A]): C def newBuilder(from: Any): Builder[A, C] = newBuilder() @@ -73,11 +43,12 @@ trait IterableFactory[+CC[_]] { def apply[A](xs: A*): CC[A] = fromIterable(View.Elems(xs: _*)) def fill[A](n: Int)(elem: => A): CC[A] = fromIterable(View.Fill(n)(elem)) def newBuilder[A](): Builder[A, CC[A]] + implicit def canBuildIterable[A]: CanBuild[A, CC[A]] = IterableFactory.toCanBuild(this) } object IterableFactory { - implicit def toSpecific[A, CC[_]](factory: IterableFactory[CC]): FromSpecificIterable[A, CC[A]] = - new FromSpecificIterable[A, CC[A]] { + implicit def toCanBuild[A, CC[_]](factory: IterableFactory[CC]): CanBuild[A, CC[A]] = + new CanBuild[A, CC[A]] { def fromSpecificIterable(it: Iterable[A]): CC[A] = factory.fromIterable[A](it) def newBuilder(): Builder[A, CC[A]] = factory.newBuilder[A]() } @@ -89,7 +60,7 @@ object IterableFactory { } } -trait SpecificIterableFactory[-A, +C] extends FromSpecificIterable[A, C] { +trait SpecificIterableFactory[-A, +C] extends CanBuild[A, C] { def empty: C def apply(xs: A*): C = fromSpecificIterable(View.Elems(xs: _*)) def fill(n: Int)(elem: => A): C = fromSpecificIterable(View.Fill(n)(elem)) @@ -102,11 +73,12 @@ trait MapFactory[+CC[X, Y]] { def fromIterable[K, V](it: Iterable[(K, V)]): CC[K, V] def apply[K, V](elems: (K, V)*): CC[K, V] = fromIterable(elems.toStrawman) def newBuilder[K, V](): Builder[(K, V), CC[K, V]] + implicit def canBuildMap[K, V]: CanBuild[(K, V), CC[K, V]] = MapFactory.toCanBuild(this) } object MapFactory { - implicit def toSpecific[K, V, CC[_, _]](factory: MapFactory[CC]): FromSpecificIterable[(K, V), CC[K, V]] = - new FromSpecificIterable[(K, V), CC[K, V]] { + implicit def toCanBuild[K, V, CC[_, _]](factory: MapFactory[CC]): CanBuild[(K, V), CC[K, V]] = + new CanBuild[(K, V), CC[K, V]] { def fromSpecificIterable(it: Iterable[(K, V)]): CC[K, V] = factory.fromIterable[K, V](it) def newBuilder(): Builder[(K, V), CC[K, V]] = factory.newBuilder[K, V]() } @@ -125,11 +97,12 @@ trait SortedIterableFactory[+CC[_]] { def apply[A : Ordering](xs: A*): CC[A] = sortedFromIterable(View.Elems(xs: _*)) def fill[A : Ordering](n: Int)(elem: => A): CC[A] = sortedFromIterable(View.Fill(n)(elem)) def newBuilder[A : Ordering](): Builder[A, CC[A]] + implicit def canBuildSortedIterable[A : Ordering]: CanBuild[A, CC[A]] = SortedIterableFactory.toCanBuild(this) } object SortedIterableFactory { - implicit def toSpecific[A: Ordering, CC[_]](factory: SortedIterableFactory[CC]): FromSpecificIterable[A, CC[A]] = - new FromSpecificIterable[A, CC[A]] { + implicit def toCanBuild[A: Ordering, CC[_]](factory: SortedIterableFactory[CC]): CanBuild[A, CC[A]] = + new CanBuild[A, CC[A]] { def fromSpecificIterable(it: Iterable[A]): CC[A] = factory.sortedFromIterable[A](it) def newBuilder(): Builder[A, CC[A]] = factory.newBuilder[A]() } @@ -148,11 +121,12 @@ trait SortedMapFactory[+CC[X, Y]] { def apply[K : Ordering, V](elems: (K, V)*): CC[K, V] = sortedFromIterable(elems.toStrawman) def newBuilder[K : Ordering, V](): Builder[(K, V), CC[K, V]] + implicit def canBuildSortedMap[K : Ordering, V]: CanBuild[(K, V), CC[K, V]] = SortedMapFactory.toCanBuild(this) } object SortedMapFactory { - implicit def toSpecific[K : Ordering, V, CC[X, Y]](factory: SortedMapFactory[CC]): FromSpecificIterable[(K, V), CC[K, V]] = - new FromSpecificIterable[(K, V), CC[K, V]] { + implicit def toCanBuild[K : Ordering, V, CC[X, Y]](factory: SortedMapFactory[CC]): CanBuild[(K, V), CC[K, V]] = + new CanBuild[(K, V), CC[K, V]] { def fromSpecificIterable(it: Iterable[(K, V)]): CC[K, V] = factory.sortedFromIterable[K, V](it) def newBuilder(): Builder[(K, V), CC[K, V]] = factory.newBuilder[K, V]() } diff --git a/src/main/scala/strawman/collection/Iterable.scala b/src/main/scala/strawman/collection/Iterable.scala index b9f3ed2638..1c486bfa47 100644 --- a/src/main/scala/strawman/collection/Iterable.scala +++ b/src/main/scala/strawman/collection/Iterable.scala @@ -251,7 +251,7 @@ trait IterableOps[+A, +CC[X], +C] extends Any { * xs.to(ArrayBuffer) * xs.to(BitSet) // for xs: Iterable[Int] */ - def to[C1](f: FromSpecificIterable[A, C1]): C1 = f.fromSpecificIterable(coll) + def to[C1](f: CanBuild[A, C1]): C1 = f.fromSpecificIterable(coll) /** Convert collection to array. */ def toArray[B >: A: ClassTag]: Array[B] = diff --git a/src/main/scala/strawman/collection/SortedMap.scala b/src/main/scala/strawman/collection/SortedMap.scala index c0b0f96bcf..49553e2f63 100644 --- a/src/main/scala/strawman/collection/SortedMap.scala +++ b/src/main/scala/strawman/collection/SortedMap.scala @@ -12,9 +12,7 @@ trait SortedMap[K, +V] trait SortedMapOps[K, +V, +CC[X, Y] <: SortedMap[X, Y] with SortedMapOps[X, Y, CC, _], +C <: SortedMap[K, V]] extends MapOps[K, V, Map, C] - with SortedOps[K, SortedSet, C] { - - def sortedIterableFactory = SortedSet + with SortedOps[K, C] { def sortedMapFactory: SortedMapFactory[CC] diff --git a/src/main/scala/strawman/collection/SortedOps.scala b/src/main/scala/strawman/collection/SortedOps.scala index 17d7ed1672..ce0e7763f8 100644 --- a/src/main/scala/strawman/collection/SortedOps.scala +++ b/src/main/scala/strawman/collection/SortedOps.scala @@ -3,12 +3,10 @@ package strawman.collection import scala.{Ordering, Option, Some} /** Base trait for sorted collections */ -trait SortedOps[A, +CC[_], +C] { +trait SortedOps[A, +C] { implicit def ordering: Ordering[A] - def sortedIterableFactory: SortedIterableFactory[CC] - /** Returns the first key of the collection. */ def firstKey: A diff --git a/src/main/scala/strawman/collection/SortedSet.scala b/src/main/scala/strawman/collection/SortedSet.scala index 70b84b3fda..6144d21a15 100644 --- a/src/main/scala/strawman/collection/SortedSet.scala +++ b/src/main/scala/strawman/collection/SortedSet.scala @@ -8,7 +8,9 @@ trait SortedSet[A] extends Set[A] with SortedSetOps[A, SortedSet, SortedSet[A]] trait SortedSetOps[A, +CC[X], +C <: SortedSet[A]] extends SetOps[A, Set, C] - with SortedOps[A, CC, C] { + with SortedOps[A, C] { + + def sortedIterableFactory: SortedIterableFactory[CC] protected[this] def sortedFromIterable[B: Ordering](it: Iterable[B]): CC[B] diff --git a/src/test/scala/strawman/collection/test/GenericTest.scala b/src/test/scala/strawman/collection/test/GenericTest.scala index 9d0becd5e1..50682337ea 100644 --- a/src/test/scala/strawman/collection/test/GenericTest.scala +++ b/src/test/scala/strawman/collection/test/GenericTest.scala @@ -30,10 +30,9 @@ object Parse { } } - def parseCollection[A, C](bf: FromSpecificIterable[A, C]) - (implicit parseA: Parse[A]): Parse[C] = { (s: String) => + def parseCollection[A, C](implicit parseA: Parse[A], cb: CanBuild[A, C]): Parse[C] = { (s: String) => val parts = s.split("\\|") - parts.foldLeft[Option[Builder[A, C]]](Some(bf.newBuilder())) { (maybeBuilder, s) => + parts.foldLeft[Option[Builder[A, C]]](Some(cb.newBuilder())) { (maybeBuilder, s) => (maybeBuilder, parseA.parse(s)) match { case (Some(builder), Some(a)) => Some(builder += a) @@ -48,10 +47,8 @@ class GenericTest { @Test def genericTest: Unit = { - assert(Parse.parseCollection[Int, immutable.List[Int]](immutable.List).parse("1|2|3").contains(1 :: 2 :: 3 :: immutable.Nil)) - - // TODO wrap with assert when HashMap’s equality is correctly implemented - Parse.parseCollection[(Int, Int), immutable.HashMap[Int, Int]](immutable.HashMap).parse("1-2|3-4").contains(immutable.HashMap((1, 2), (3, 4))) + assert(Parse.parseCollection[Int, immutable.List[Int]].parse("1|2|3").contains(1 :: 2 :: 3 :: immutable.Nil)) + assert(Parse.parseCollection[(Int, Int), immutable.HashMap[Int, Int]].parse("1-2|3-4").contains(immutable.HashMap((1, 2), (3, 4)))) } } diff --git a/src/test/scala/strawman/collection/test/TraverseTest.scala b/src/test/scala/strawman/collection/test/TraverseTest.scala index 79e6cfdd8d..d2be269d49 100644 --- a/src/test/scala/strawman/collection/test/TraverseTest.scala +++ b/src/test/scala/strawman/collection/test/TraverseTest.scala @@ -19,7 +19,7 @@ class TraverseTest { case (Some(builder), Some(a)) => Some(builder += a) case _ => None }.map(_.result()) - def optionSequence1[CC[X] <: Iterable[X] with SortedOps[X, CC, CC[X]], A : Ordering](xs: CC[Option[A]]): Option[CC[A]] = + def optionSequence1[CC[X] <: SortedSet[X] with SortedSetOps[X, CC, CC[X]], A : Ordering](xs: CC[Option[A]]): Option[CC[A]] = xs.foldLeft[Option[Builder[A, CC[A]]]](Some(xs.sortedIterableFactory.newBuilder[A]())) { case (Some(builder), Some(a)) => Some(builder += a) case _ => None @@ -134,6 +134,10 @@ class TraverseTest { val xs7 = immutable.HashMap((1, "1"), (2, "2")) val xs8 = flatCollect(xs7) { case (2, v) => immutable.List((v, v)) } val xs9: immutable.HashMap[String, String] = xs8 + + val xs10 = immutable.TreeSet(1, 2, 3) + val xs11 = flatCollect(xs10) { case 2 => immutable.List("foo", "bar") } + val xs12: immutable.TreeSet[String] = xs11 } @Test