@@ -130,7 +130,7 @@ trait IterableOps[+A, +CC[_], +C] {
130130}
131131~~~
132132
133- And then leaf collection types appropriately instantiate the type
133+ Leaf collection types appropriately instantiate the type
134134parameters. For instance, in the case of ` List[A] ` we want ` CC ` to
135135be ` List ` and ` C ` to be ` List[A] ` :
136136
@@ -177,14 +177,15 @@ def map[K2, V2](f: ((K, V)) => (K2, V2)): Map[K2, V2]
177177def map [B ](f : ((K , V )) => B ): Iterable [B ]
178178~~~
179179
180- At use-site, if you call the ` map ` operation, the overloading resolution rules
181- first try the definition that comes from ` MapOps ` (because ` MapOps ` is more
182- specific than ` IterableOps ` ), which returns a ` Map ` , but if it doesn’t type
183- check (in case the return type of the function passed to the ` map ` call is not
184- a pair), it fallbacks to the definition from ` IterableOps ` , which returns an
185- ` Iterable ` . This is how we follow the “same-result-type” principle: wherever
186- possible a transformation method on a collection yields a collection of the
187- same type.
180+ At use-site, when you call the ` map ` operation, the compiler selects one of
181+ the two overloads. If the function passed as argument to ` map ` returns a pair,
182+ both functions are applicable. In this case, the version from ` MapOps ` is used
183+ because it is more specific by the rules of overloading resolution, so the
184+ resulting collection is a ` Map ` . If the argument function does not return a pair,
185+ only the version defined in ` IterableOps ` is applicable. In this case, the
186+ resulting collection is an ` Iterable ` . This is how we follow the
187+ “same-result-type” principle: wherever possible a transformation method on a
188+ collection yields a collection of the same type.
188189
189190In summary, the fact that ` Map ` collection types take two type parameters makes
190191it impossible to unify their transformation operations with the ones from
@@ -405,7 +406,7 @@ The first task is to find the supertype of our collection: is it
405406` Seq ` , ` Set ` , ` Map ` or just ` Iterable ` ? In our case, it is tempting
406407to choose ` Seq ` because our collection can contain duplicates and
407408iteration order is determined by insertion order. However, some
408- properties of [ ` Seq ` ] ( /overviews/collections/seqs.html ) are not satisfied:
409+ [ properties of ` Seq ` ] ( /overviews/collections/seqs.html ) are not satisfied:
409410
410411~~~ scala
411412(xs ++ ys).size == xs.size + ys.size
@@ -507,8 +508,8 @@ You can see that if we try to grow the collection with more than four
507508elements, the first elements are dropped (see ` res4 ` ). The operations
508509behave as expected except for the last one: after calling ` take ` we
509510get back a ` List ` instead of the expected ` Capped1 ` collection. This
510- is because all that was done in class
511- [ ` Capped1 ` ] ( #first-version-of-capped-class ) was making ` Capped1 ` extend
511+ is because all that was done in [ class
512+ ` Capped1 ` ] ( #first-version-of-capped-class ) was making ` Capped1 ` extend
512513` immutable.Iterable ` . This class has a ` take ` method
513514that returns an ` immutable.Iterable ` , and that’s implemented in terms of
514515` immutable.Iterable ` ’s default implementation, ` List ` . So, that’s what
@@ -531,6 +532,8 @@ effect, as shown in the next section.
531532### Second version of ` Capped ` class ###
532533
533534~~~ scala
535+ import scala .collection ._
536+
534537class Capped2 [A ] private (val capacity : Int , val length : Int , offset : Int , elems : Array [Any ])
535538 extends immutable.Iterable [A ]
536539 with IterableOps [A , Capped2 , Capped2 [A ]] { self =>
@@ -554,8 +557,8 @@ class Capped2Factory(capacity: Int) extends IterableFactory[Capped2] {
554557
555558 def empty [A ]: Capped2 [A ] = new Capped2 [A ](capacity)
556559
557- def newBuilder [A ]: Builder [A , Capped2 [A ]] =
558- new ImmutableBuilder [A , Capped2 [A ]](empty) {
560+ def newBuilder [A ]: mutable. Builder [A , Capped2 [A ]] =
561+ new mutable. ImmutableBuilder [A , Capped2 [A ]](empty) {
559562 def addOne (elem : A ): this .type = { elems = elems :+ elem; this }
560563 }
561564}
@@ -618,6 +621,8 @@ strict implementations of transformation operations.
618621### Final version of ` Capped ` class ###
619622
620623~~~ scala
624+ import scala .collection ._
625+
621626final class Capped [A ] private (val capacity : Int , val length : Int , offset : Int , elems : Array [Any ])
622627 extends immutable.Iterable [A ]
623628 with IterableOps [A , Capped , Capped [A ]]
@@ -667,8 +672,8 @@ class CappedFactory(capacity: Int) extends IterableFactory[Capped] {
667672
668673 def empty [A ]: Capped [A ] = new Capped [A ](capacity)
669674
670- def newBuilder [A ]: Builder [A , Capped [A ]] =
671- new ImmutableBuilder [A , Capped [A ]](empty) {
675+ def newBuilder [A ]: mutable. Builder [A , Capped [A ]] =
676+ new mutable. ImmutableBuilder [A , Capped [A ]](empty) {
672677 def addOne (elem : A ): this .type = { elems = elems :+ elem; this }
673678 }
674679
@@ -730,6 +735,7 @@ representation.
730735
731736### First version of RNA strands class ###
732737
738+ import collection.mutable
733739 import collection.immutable.{ IndexedSeq, IndexedSeqOps }
734740
735741 final class RNA1 private (
@@ -748,7 +754,7 @@ representation.
748754
749755 override protected def fromSpecificIterable(coll: Iterable[Base]): RNA1 =
750756 fromSeq(coll.toSeq)
751- override protected def newSpecificBuilder: Builder[Base, RNA1] =
757+ override protected def newSpecificBuilder: mutable. Builder[Base, RNA1] =
752758 iterableFactory.newBuilder[Base].mapResult(fromSeq)
753759 }
754760
@@ -763,7 +769,7 @@ representation.
763769 // Bitmask to isolate a group
764770 private val M = (1 << S) - 1
765771
766- def fromSeq(buf: Seq[Base]): RNA1 = {
772+ def fromSeq(buf: collection. Seq[Base]): RNA1 = {
767773 val groups = new Array[Int]((buf.length + N - 1) / N)
768774 for (i <- 0 until buf.length)
769775 groups(i / N) |= Base.toInt(buf(i)) << (i % N * S)
@@ -920,14 +926,17 @@ this is why we always get a `Vector` as a result.
920926
921927### Second version of RNA strands class ###
922928
929+ import scala.collection.{ View, mutable }
930+ import scala.collection.immutable.{ IndexedSeq, IndexedSeqOps }
931+
923932 final class RNA2 private (val groups: Array[Int], val length: Int)
924933 extends IndexedSeq[Base] with IndexedSeqOps[Base, IndexedSeq, RNA2] {
925934
926935 import RNA2._
927936
928937 def apply(idx: Int): Base = // as before
929938 override protected def fromSpecificIterable(coll: Iterable[Base]): RNA2 = // as before
930- override protected def newSpecificBuilder: Builder[Base, RNA2] = // as before
939+ override protected def newSpecificBuilder: mutable. Builder[Base, RNA2] = // as before
931940
932941 // Overloading of `appended`, `prepended`, `appendedAll`,
933942 // `prependedAll`, `map`, `flatMap` and `concat` to return an `RNA2`
@@ -975,6 +984,9 @@ scala> bases.to(RNA2)
975984### Final version of RNA strands class ###
976985
977986~~~ scala
987+ import scala .collection .{ AbstractIterator , SpecificIterableFactory , StrictOptimizedSeqOps , View , mutable }
988+ import scala .collection .immutable .{ IndexedSeq , IndexedSeqOps }
989+
978990final class RNA private (
979991 val groups : Array [Int ],
980992 val length : Int
@@ -995,16 +1007,16 @@ final class RNA private (
9951007 // `newSpecificBuilder`, from `IterableOps`
9961008 override protected def fromSpecificIterable (coll : Iterable [Base ]): RNA =
9971009 RNA .fromSpecific(coll)
998- override protected def newSpecificBuilder : Builder [Base , RNA ] =
1010+ override protected def newSpecificBuilder : mutable. Builder [Base , RNA ] =
9991011 RNA .newBuilder
10001012
10011013 // Overloading of `appended`, `prepended`, `appendedAll`, `prependedAll`,
10021014 // `map`, `flatMap` and `concat` to return an `RNA` when possible
1003- def appended (base : Base ): RNA =
1015+ def appended (base : Base ): RNA =
10041016 (newSpecificBuilder ++= this += base).result()
10051017 def appendedAll (suffix : Iterable [Base ]): RNA =
10061018 (newSpecificBuilder ++= this ++= suffix).result()
1007- def prepended (base : Base ): RNA =
1019+ def prepended (base : Base ): RNA =
10081020 (newSpecificBuilder += base ++= this ).result()
10091021 def prependedAll (prefix : Iterable [Base ]): RNA =
10101022 (newSpecificBuilder ++= prefix ++= this ).result()
@@ -1050,7 +1062,7 @@ object RNA extends SpecificIterableFactory[Base, RNA] {
10501062 private val M = (1 << S ) - 1 // bitmask to isolate a group
10511063 private val N = 32 / S // number of groups in an Int
10521064
1053- def fromSeq (buf : Seq [Base ]): RNA = {
1065+ def fromSeq (buf : collection. Seq [Base ]): RNA = {
10541066 val groups = new Array [Int ]((buf.length + N - 1 ) / N )
10551067 for (i <- 0 until buf.length)
10561068 groups(i / N ) |= Base .toInt(buf(i)) << (i % N * S )
@@ -1061,12 +1073,12 @@ object RNA extends SpecificIterableFactory[Base, RNA] {
10611073 // and `fromSpecific`
10621074 def empty : RNA = fromSeq(Seq .empty)
10631075
1064- def newBuilder () : Builder [Base , RNA ] =
1065- ArrayBuffer .newBuilder[Base ]() .mapResult(fromSeq)
1076+ def newBuilder : mutable. Builder [Base , RNA ] =
1077+ mutable. ArrayBuffer .newBuilder[Base ].mapResult(fromSeq)
10661078
10671079 def fromSpecific (it : IterableOnce [Base ]): RNA = it match {
1068- case seq : Seq [Base ] => fromSeq(seq)
1069- case _ => fromSeq(ArrayBuffer .from(it))
1080+ case seq : collection. Seq [Base ] => fromSeq(seq)
1081+ case _ => fromSeq(mutable. ArrayBuffer .from(it))
10701082 }
10711083}
10721084~~~
@@ -1079,7 +1091,7 @@ The final [`RNA` class](#final-version-of-rna-strands-class):
10791091 an ` RNA ` ,
10801092- has a companion object that extends ` SpecificIterableFactory[Base, RNA] ` , which makes
10811093 it possible to use it as a parameter of a ` to ` call (to convert any collection
1082- of bases to an ` RNA ` ),
1094+ of bases to an ` RNA ` , e.g. ` List(U, A, G, C).to(RNA) ` ),
10831095- moves the ` newSpecificBuilder ` and ` fromSpecificIterable ` implementations
10841096 to the companion object.
10851097
@@ -1329,7 +1341,12 @@ We'll now turn to the companion object `PrefixMap`. In fact it is not
13291341strictly necessary to define this companion object, as class ` PrefixMap `
13301342can stand well on its own. The main purpose of object ` PrefixMap ` is to
13311343define some convenience factory methods. It also defines an implicit
1332- ` Factory ` for a better interoperability with other collections.
1344+ conversion to ` Factory ` for a better interoperability with other
1345+ collections. This conversion is triggered when one writes, for instance,
1346+ ` List("foo" -> 3).to(PrefixMap) ` . The ` to ` operation takes a ` Factory `
1347+ as parameter but the ` PrefixMap ` companion object does not extend ` Factory ` (and it
1348+ can not because a ` Factory ` fixes the type of collection elements,
1349+ whereas ` PrefixMap ` has a polymorphic type of values).
13331350
13341351The two convenience methods are ` empty ` and ` apply ` . The same methods are
13351352present for all other collections in Scala's collection framework so
@@ -1375,6 +1392,10 @@ You want to add overloads to specialize transformation operations such that they
13751392- ` map ` , on ` SortedSet ` , when an implicit ` Ordering ` is available for the resulting element type, should return a
13761393` SortedSet ` (instead of a ` Set ` ).
13771394
1395+ Typically, this happens when the collection fixes some type parameter of its template trait. For instance in
1396+ the case of the ` RNA ` collection type, we fix the element type to ` Base ` , and in the case of the ` PrefixMap[A] `
1397+ collection type, we fix the type of keys to ` String ` .
1398+
13781399The following table lists transformation operations that might return an undesirably wide type. You might want to overload
13791400these operations to return a more specific type.
13801401
@@ -1412,3 +1433,7 @@ unmanagedSourceDirectories in Compile += {
14121433And then you can define a Scala 2.13 compatible implementation of your collection
14131434in the ` src/main/scala-2.13+ ` source directory, and an implementation for the
14141435previous Scala versions in the ` src/main/scala-2.13- ` source directory.
1436+
1437+ You can see how this has been put in practice in
1438+ [ scalacheck] ( https://github.com/rickynils/scalacheck/pull/411 ) and
1439+ [ scalaz] ( https://github.com/scalaz/scalaz/pull/1730 ) .
0 commit comments