Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 14 additions & 40 deletions src/main/scala/strawman/collection/Factories.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These definitions are not anymore necessary: they have been superseded by the implicit definitions in factories.


/**
* 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()
Expand All @@ -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]()
}
Expand All @@ -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))
Expand All @@ -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]()
}
Expand All @@ -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]()
}
Expand All @@ -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]()
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/strawman/collection/Iterable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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] =
Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/strawman/collection/SortedMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/strawman/collection/SortedOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion src/main/scala/strawman/collection/SortedSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
11 changes: 4 additions & 7 deletions src/test/scala/strawman/collection/test/GenericTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The factory is now provided implicitly, which was the initial goal of this PR.

}

}
6 changes: 5 additions & 1 deletion src/test/scala/strawman/collection/test/TraverseTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down