diff --git a/.travis.yml b/.travis.yml index ba8f8c6..7b53b78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ jdk: - openjdk11 scala: - - 2.13.0-M4 + - 2.13.0-RC1 script: - sbt ++$TRAVIS_SCALA_VERSION test diff --git a/build.sbt b/build.sbt index 5b86413..10771f6 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ // TODO Make it a cross project including Scala.js -scalaVersion := "2.13.0-M4" +scalaVersion := "2.13.0-RC1" organization := "org.scala-lang" diff --git a/src/main/scala/scala/collection/MultiDict.scala b/src/main/scala/scala/collection/MultiDict.scala index ee29d0f..978dda4 100644 --- a/src/main/scala/scala/collection/MultiDict.scala +++ b/src/main/scala/scala/collection/MultiDict.scala @@ -1,6 +1,5 @@ package scala.collection -import annotation.unchecked.uncheckedVariance import scala.util.hashing.MurmurHash3 /** @@ -14,10 +13,11 @@ trait MultiDict[K, V] with MultiDictOps[K, V, MultiDict, MultiDict[K, V]] with Equals { - def multiMapFactory: MapFactory[MultiDictCC] = MultiDict - - override protected[this] def fromSpecificIterable(coll: Iterable[(K, V)]): MultiDictCC[K, V] = multiMapFactory.from(coll) - override protected[this] def newSpecificBuilder: mutable.Builder[(K, V), MultiDictCC[K, V]] = multiMapFactory.newBuilder[K, V] + def multiDictFactory: MapFactory[MultiDict] = MultiDict + override protected def fromSpecific(coll: IterableOnce[(K, V)]): MultiDict[K, V] = multiDictFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(K, V), MultiDict[K, V]] = multiDictFactory.newBuilder + override def empty: MultiDict[K, V] = multiDictFactory.empty + override def withFilter(p: ((K, V)) => Boolean): MultiDictOps.WithFilter[K, V, Iterable, MultiDict] = new MultiDictOps.WithFilter(this, p) def canEqual(that: Any): Boolean = true @@ -43,18 +43,16 @@ trait MultiDict[K, V] trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]] extends IterableOps[(K, V), Iterable, C] { - protected[this] type MultiDictCC[K, V] = CC[K, V] @uncheckedVariance - - def multiMapFactory: MapFactory[MultiDictCC] + def multiDictFactory: MapFactory[CC] - protected[this] def multiMapFromIterable[L, W](it: Iterable[(L, W)]): CC[L, W] = - multiMapFactory.from(it) + protected def multiDictFromIterable[L, W](it: Iterable[(L, W)]): CC[L, W] = + multiDictFactory.from(it) - protected[this] def fromSpecificSets(it: Iterable[(K, Set[V])]): C = - fromSpecificIterable(it.view.flatMap { case (k, vs) => vs.view.map(v => (k, v)) }) + protected def fromSpecificSets(it: Iterable[(K, Set[V])]): C = + fromSpecific(it.view.flatMap { case (k, vs) => vs.view.map(v => (k, v)) }) - protected[this] def fromSets[L, W](it: Iterable[(L, Set[W])]): CC[L, W] = - multiMapFromIterable(it.view.flatMap { case (k, vs) => vs.view.map(v => (k, v)) }) + protected def fromSets[L, W](it: Iterable[(L, Set[W])]): CC[L, W] = + multiDictFromIterable(it.view.flatMap { case (k, vs) => vs.view.map(v => (k, v)) }) /** * @return All the elements contained in this multidict, grouped by key @@ -104,7 +102,7 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]] * @tparam W new type of values */ def map[L, W](f: ((K, V)) => (L, W)): CC[L, W] = - multiMapFromIterable(new View.Map(toIterable, f)) + multiDictFromIterable(new View.Map(toIterable, f)) /** * @return a multidict that contains all the entries of `this` multidict, @@ -115,7 +113,7 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]] * @tparam W new type of values */ def flatMap[L, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = - multiMapFromIterable(new View.FlatMap(toIterable, f)) + multiDictFromIterable(new View.FlatMap(toIterable, f)) /** * @return a multidict that contains all the entries of `this` multidict @@ -133,11 +131,10 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]] ) /** Concatenate the entries given in `that` iterable to `this` multidict */ - def concat(that: Iterable[(K, V)]): C = - fromSpecificIterable(new View.Concat(toIterable, that)) - - override def withFilter(p: ((K, V)) => Boolean): MultiDictOps.WithFilter[K, V, IterableCC, CC] = - new MultiDictOps.WithFilter(this, p) + def concat(that: IterableOnce[(K, V)]): C = fromSpecific(that match { + case that: collection.Iterable[(K, V)] => new View.Concat(toIterable, that) + case _ => iterator ++ that.iterator + }) /** * @return Whether there exists a value associated with the given `key` @@ -209,10 +206,10 @@ object MultiDictOps { ) extends IterableOps.WithFilter[(K, V), IterableCC](`this`, p) { def map[L, W](f: ((K, V)) => (L, W)): CC[L, W] = - `this`.multiMapFactory.from(new View.Map(filtered, f)) + `this`.multiDictFactory.from(new View.Map(filtered, f)) def flatMap[L, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = - `this`.multiMapFactory.from(new View.FlatMap(filtered, f)) + `this`.multiDictFactory.from(new View.FlatMap(filtered, f)) override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, CC] = new WithFilter[K, V, IterableCC, CC](`this`, (kv: (K, V)) => p(kv) && q(kv)) diff --git a/src/main/scala/scala/collection/MultiSet.scala b/src/main/scala/scala/collection/MultiSet.scala index 53ee857..ad1a402 100644 --- a/src/main/scala/scala/collection/MultiSet.scala +++ b/src/main/scala/scala/collection/MultiSet.scala @@ -12,6 +12,11 @@ trait MultiSet[A] with MultiSetOps[A, MultiSet, MultiSet[A]] with Equals { + override def iterableFactory: IterableFactory[MultiSet] = MultiSet + override protected def fromSpecific(coll: IterableOnce[A]): MultiSet[A] = iterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, MultiSet[A]] = iterableFactory.newBuilder + override def empty: MultiSet[A] = iterableFactory.empty + def canEqual(that: Any): Boolean = true override def equals(o: Any): Boolean = o match { @@ -36,11 +41,11 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] extends IterableOps[A, CC, C] { protected[this] def fromSpecificOccurrences(it: Iterable[(A, Int)]): C = - fromSpecificIterable(it.view.flatMap { case (e, n) => new View.Fill(n)(e) }) + fromSpecific(it.view.flatMap { case (e, n) => new View.Fill(n)(e) }) protected[this] def fromOccurrences[E](it: Iterable[(E, Int)]): CC[E] = // Note new MultiSet(it.to(Map)) would be more efficient but would also loose duplicates - fromIterable(it.view.flatMap { case (e, n) => new View.Fill(n)(e) }) + iterableFactory.from(it.view.flatMap { case (e, n) => new View.Fill(n)(e) }) /** * @return All the elements contained in this multiset and their number of occurrences @@ -68,8 +73,10 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] * * @param that the collection of elements to add to this multiset */ - def concat(that: Iterable[A]): C = - fromSpecificIterable(new View.Concat(toIterable, that)) + def concat(that: IterableOnce[A]): C = fromSpecific(that match { + case that: collection.Iterable[A] => new View.Concat(this, that) + case _ => iterator.concat(that.iterator) + }) /** * @return a new multiset summing the occurrences of this multiset diff --git a/src/main/scala/scala/collection/SortedMultiDict.scala b/src/main/scala/scala/collection/SortedMultiDict.scala index ad8c2bc..43ffb9d 100644 --- a/src/main/scala/scala/collection/SortedMultiDict.scala +++ b/src/main/scala/scala/collection/SortedMultiDict.scala @@ -1,7 +1,5 @@ package scala.collection -import annotation.unchecked.uncheckedVariance - /** * A multidict whose keys are sorted * @tparam K the type of keys @@ -13,19 +11,21 @@ trait SortedMultiDict[K, V] def unsorted: MultiDict[K, V] = this - override protected[this] def fromSpecificIterable(coll: Iterable[(K, V)]): SortedMultiDictCC[K, V] = sortedMultiMapFactory.from(coll) - override protected[this] def newSpecificBuilder: mutable.Builder[(K, V), SortedMultiDictCC[K, V]] = sortedMultiMapFactory.newBuilder[K, V] + def sortedMultiDictFactory: SortedMapFactory[SortedMultiDict] = SortedMultiDict + override protected def fromSpecific(coll: IterableOnce[(K, V)]): SortedMultiDict[K, V] = sortedMultiDictFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(K, V), SortedMultiDict[K, V]] = sortedMultiDictFactory.newBuilder + override def empty: SortedMultiDict[K, V] = sortedMultiDictFactory.empty + override def withFilter(p: ((K, V)) => Boolean): SortedMultiDictOps.WithFilter[K, V, Iterable, MultiDict, SortedMultiDict] = new SortedMultiDictOps.WithFilter(this, p) + } trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]] extends MultiDictOps[K, V, MultiDict, C] with SortedOps[K, C] { - protected[this] type SortedMultiDictCC[X, Y] = CC[X, Y] @uncheckedVariance + def sortedMultiDictFactory: SortedMapFactory[CC] - def sortedMultiMapFactory: SortedMapFactory[SortedMultiDictCC] - - protected[this] def sortedFromIterable[L : Ordering, W](it: Iterable[(L, W)]): CC[L, W] + protected[this] def sortedFromIterable[L : Ordering, W](it: Iterable[(L, W)]): CC[L, W] = sortedMultiDictFactory.from(it) protected[this] def sortedFromSets[L : Ordering, W](it: Iterable[(L, Set[W])]): CC[L, W] = sortedFromIterable(it.view.flatMap { case (l, ws) => ws.map(w => (l, w)) }) @@ -52,9 +52,6 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, rangeUntil(next) } - override def withFilter(p: ((K, V)) => Boolean): SortedMultiDictOps.WithFilter[K, V, IterableCC, MultiDictCC, CC] = - new SortedMultiDictOps.WithFilter[K, V, IterableCC, MultiDictCC, CC](this, p) - /** * @return a sorted multidict that contains all the entries of `this` sorted multidict, * transformed by the function `f` @@ -134,10 +131,10 @@ object SortedMultiDictOps { ) extends MultiDictOps.WithFilter[K, V, IterableCC, MultiDictCC](`this`, p) { def map[L : Ordering, W](f: ((K, V)) => (L, W)): CC[L, W] = - `this`.sortedMultiMapFactory.from(new View.Map(filtered, f)) + `this`.sortedMultiDictFactory.from(new View.Map(filtered, f)) def flatMap[L : Ordering, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = - `this`.sortedMultiMapFactory.from(new View.FlatMap(filtered, f)) + `this`.sortedMultiDictFactory.from(new View.FlatMap(filtered, f)) override def withFilter(q: ((K, V)) => Boolean): WithFilter[K, V, IterableCC, MultiDictCC, CC] = new WithFilter[K, V, IterableCC, MultiDictCC, CC](`this`, kv => p(kv) && q(kv)) diff --git a/src/main/scala/scala/collection/SortedMultiSet.scala b/src/main/scala/scala/collection/SortedMultiSet.scala index 7763ef2..9f2a8e9 100644 --- a/src/main/scala/scala/collection/SortedMultiSet.scala +++ b/src/main/scala/scala/collection/SortedMultiSet.scala @@ -12,24 +12,22 @@ trait SortedMultiSet[A] def unsorted: MultiSet[A] = this - override protected[this] def fromSpecificIterable(coll: Iterable[A]): SortedIterableCC[A] = sortedIterableFactory.from(coll) - override protected[this] def newSpecificBuilder: mutable.Builder[A, SortedIterableCC[A]] = sortedIterableFactory.newBuilder[A] + def sortedIterableFactory: SortedIterableFactory[SortedMultiSet] = SortedMultiSet + override protected def fromSpecific(coll: IterableOnce[A]): SortedMultiSet[A] = sortedIterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, SortedMultiSet[A]] = sortedIterableFactory.newBuilder + override def empty: SortedMultiSet[A] = sortedIterableFactory.empty + override def withFilter(p: A => Boolean): SortedMultiSetOps.WithFilter[A, MultiSet, SortedMultiSet] = new SortedMultiSetOps.WithFilter(this, p) - protected[this] def sortedFromIterable[B : Ordering](it: scala.collection.Iterable[B]): SortedIterableCC[B] = sortedIterableFactory.from(it) - - def sortedIterableFactory: SortedIterableFactory[SortedIterableCC] = SortedMultiSet } trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] extends MultiSetOps[A, MultiSet, C] with SortedOps[A, C] { - protected[this] type SortedIterableCC[X] = CC[X] @uncheckedVariance - - def sortedIterableFactory: SortedIterableFactory[SortedIterableCC] + def sortedIterableFactory: SortedIterableFactory[CC] - protected[this] def sortedFromIterable[B : Ordering](it: Iterable[B]): SortedIterableCC[B] - protected[this] def sortedFromOccurrences[B : Ordering](it: Iterable[(B, Int)]): CC[B] = + protected def sortedFromIterable[B : Ordering](it: Iterable[B]): CC[B] = sortedIterableFactory.from(it) + protected def sortedFromOccurrences[B : Ordering](it: Iterable[(B, Int)]): CC[B] = sortedFromIterable(it.view.flatMap { case (b, n) => new View.Fill(n)(b) }) /** `this` sorted multiset upcasted to an unsorted multiset */ @@ -62,9 +60,6 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] rangeUntil(next) } - override def withFilter(p: A => Boolean): SortedMultiSetOps.WithFilter[A, IterableCC, CC] = - new SortedMultiSetOps.WithFilter(this, p) - /** Builds a new sorted multiset by applying a function to all elements of this sorted multiset. * * @param f the function to apply to each element. @@ -165,7 +160,7 @@ object SortedMultiSetOps { class WithFilter[A, +IterableCC[_], +CC[X] <: MultiSet[X]]( `this`: SortedMultiSetOps[A, CC, _] with IterableOps[A, IterableCC, _], p: A => Boolean - ) extends IterableOps.WithFilter(`this`, p) { + ) extends IterableOps.WithFilter[A, IterableCC](`this`, p) { def map[B : Ordering](f: A => B): CC[B] = `this`.sortedIterableFactory.from(new View.Map(filtered, f)) diff --git a/src/main/scala/scala/collection/decorators/HasImmutableMapOps.scala b/src/main/scala/scala/collection/decorators/HasImmutableMapOps.scala deleted file mode 100644 index 0a6481b..0000000 --- a/src/main/scala/scala/collection/decorators/HasImmutableMapOps.scala +++ /dev/null @@ -1,43 +0,0 @@ -package scala.collection -package decorators - -/** - * Type class witnessing that a collection type `C` has - * a conversion to `immutable.MapOps[K, V, _, _]`. - * - * @see [[scala.collection.decorators.HasIterableOps]] - */ -trait HasImmutableMapOps[C] extends HasMapOps[C] { - - // Convenient intermediate type definitions to satisfy type bounds - protected type _CC[X, +Y] <: immutable.MapOps[X, Y, _CC, _] - protected type _C <: immutable.MapOps[K, V, _CC, _C] - - /** A conversion from the type `C` to `immutable.MapOps[K, V, _, _]` */ - def apply(c: C): immutable.MapOps[K, V, _CC, _C] - -} - -object HasImmutableMapOps { - - // 1. Map collections - implicit def mapHasMapOps[CC[X, +Y] <: immutable.MapOps[X, Y, CC, CC[X, Y]], K0, V0]: HasImmutableMapOps[CC[K0, V0]] { type K = K0; type V = V0 } = - new HasImmutableMapOps[CC[K0, V0]] { - type K = K0 - type V = V0 - type _CC[X, +Y] = CC[X, Y] - type _C = CC[K, V] - def apply(c: CC[K0, V0]): immutable.MapOps[K0, V0, _CC, _C] = c - } - - // 2. Sorted Map collections - implicit def sortedMapHasMapOps[CC[X, +Y] <: immutable.Map[X, Y] with immutable.SortedMapOps[X, Y, CC, CC[X, Y]], K0, V0]: HasImmutableMapOps[CC[K0, V0]] { type K = K0; type V = V0 } = - new HasImmutableMapOps[CC[K0, V0]] { - type K = K0 - type V = V0 - type _CC[X, +Y] = immutable.Map[X, Y] - type _C = _CC[K, V] - def apply(c: CC[K0, V0]): immutable.MapOps[K0, V0, _CC, _C] = c - } - -} \ No newline at end of file diff --git a/src/main/scala/scala/collection/decorators/HasIterableOps.scala b/src/main/scala/scala/collection/decorators/HasIterableOps.scala deleted file mode 100644 index 5bfe641..0000000 --- a/src/main/scala/scala/collection/decorators/HasIterableOps.scala +++ /dev/null @@ -1,44 +0,0 @@ -package scala.collection -package decorators - -/** - * Type class witnessing that a collection type `C` - * has elements of type `A` and has a conversion to `IterableOps[A, _, _]`. - * - * This type enables simple enrichment of `Iterable`s with extension methods. - * - * @tparam C Collection type (e.g. `List[Int]`) - */ -trait HasIterableOps[C] { - - /** The type of elements (e.g. `Int`) */ - type A - - /** A conversion from the type `C` to `IterableOps[A, _, _]` */ - def apply(c: C): IterableOps[A, AnyConstr, _] - -} - -object HasIterableOps extends LowPriorityHasIterableOps { - - implicit def iterableHasIterableOps[CC[X] <: IterableOps[X, AnyConstr, _], A0]: HasIterableOps[CC[A0]] { type A = A0 } = - new HasIterableOps[CC[A0]] { - type A = A0 - def apply(c: CC[A0]): IterableOps[A0, AnyConstr, _] = c - } - -} - -trait LowPriorityHasIterableOps { - - // Makes `HasSeqOps` instances visible in `HasIterableOps` companion - implicit def hasSeqOpsHasIterableOps[C, A0](implicit - hasSeqOps: HasSeqOps[C] { type A = A0 } - ): HasIterableOps[C] { type A = A0 } = hasSeqOps - - // Makes `HasMapOps` instances visible in `HasIterableOps` companion - implicit def hasMapOpsHasIterableOps[C, K0, V0](implicit - hasMapOps: HasMapOps[C] { type K = K0; type V = V0 } - ): HasIterableOps[C] { type A = (K0, V0) } = hasMapOps - -} \ No newline at end of file diff --git a/src/main/scala/scala/collection/decorators/HasMapOps.scala b/src/main/scala/scala/collection/decorators/HasMapOps.scala deleted file mode 100644 index 65e305b..0000000 --- a/src/main/scala/scala/collection/decorators/HasMapOps.scala +++ /dev/null @@ -1,46 +0,0 @@ -package scala.collection -package decorators - -/** - * Type class witnessing that a collection type `C` - * has keys of type `K`, values of type `V` and has a conversion to `MapOps[K, V, _, _]`. - * - * This type enables simple enrichment of `Map`s with extension methods. - * - * @tparam C Collection type (e.g. `Map[Int, String]`) - */ -trait HasMapOps[C] extends HasIterableOps[C] { - - /** The type of keys */ - type K - - /** The type of values */ - type V - - type A = (K, V) - - /** A conversion from the type `C` to `MapOps[K, V, _, _]` */ - def apply(c: C): MapOps[K, V, ({ type l[X, +Y] = IterableOps[_, AnyConstr, _] })#l, _] - -} - -object HasMapOps extends LowPriorityHasMapOps { - - // 1. Map collections - implicit def mapHasMapOps[CC[X, +Y] <: MapOps[X, Y, ({ type l[X, +Y] = IterableOps[_, AnyConstr, _] })#l, _], K0, V0]: HasMapOps[CC[K0, V0]] { type K = K0; type V = V0 } = - new HasMapOps[CC[K0, V0]] { - type K = K0 - type V = V0 - def apply(c: CC[K0, V0]): MapOps[K0, V0, ({ type l[X, +Y] = IterableOps[_, AnyConstr, _] })#l, _] = c - } - -} - -trait LowPriorityHasMapOps { - - // Makes `HasImmutableMapOps` instances visible in `HasMapOps` companion - implicit def hasImmutableMapOpsHasMapOps[C, K0, V0](implicit - hasImmutableMapOps: HasImmutableMapOps[C] { type K = K0; type V = V0 } - ): HasMapOps[C] { type K = K0; type V = V0 } = hasImmutableMapOps - -} \ No newline at end of file diff --git a/src/main/scala/scala/collection/decorators/HasSeqOps.scala b/src/main/scala/scala/collection/decorators/HasSeqOps.scala deleted file mode 100644 index 36b64c6..0000000 --- a/src/main/scala/scala/collection/decorators/HasSeqOps.scala +++ /dev/null @@ -1,58 +0,0 @@ -package scala.collection -package decorators - -import scala.collection.immutable.{ArraySeq, Range} - -/** Type class witnessing that a collection type `C` has - * elements of type `A` and has a conversion to `SeqOps[A, _, _]`. - * - * This type enables simple enrichment of `Seq`s with extension methods which - * can make full use of the mechanics of the Scala collections framework in - * their implementation. - * - * @see [[scala.collection.decorators.HasIterableOps]] - */ -trait HasSeqOps[C] extends HasIterableOps[C] { - /** A conversion from the type `C` to `SeqOps[A, _, _]`. */ - def apply(c: C): SeqOps[A, AnyConstr, _] -} - -object HasSeqOps { - - // we want to provide implicit instances that unify all possible types `X` with a `SeqOps[A, CC, C]` - // 1. Seq collections - implicit def seqHasSeqOps[CC[X] <: SeqOps[X, AnyConstr, _], A0]: HasSeqOps[CC[A0]] {type A = A0 } = - new HasSeqOps[CC[A0]] { - type A = A0 - def apply(c: CC[A0]): SeqOps[A0, AnyConstr, _] = c - } - - // 2. String - implicit def stringHasSeqOps: HasSeqOps[String] { type A = Char } = - new HasSeqOps[String] { - type A = Char - def apply(c: String): SeqOps[Char, AnyConstr, _] = c: Seq[Char] - } - - // 3. StringView - implicit def stringViewHasSeqOps: HasSeqOps[StringView] { type A = Char } = - new HasSeqOps[StringView] { - type A = Char - def apply(c: StringView): SeqOps[Char, AnyConstr, _] = c - } - - // 4. Array - implicit def arrayHasSeqOps[A0]: HasSeqOps[Array[A0]] { type A = A0 } = - new HasSeqOps[Array[A0]] { - type A = A0 - def apply(c: Array[A0]): SeqOps[A0, AnyConstr, _] = mutable.ArraySeq.make(c) - } - - // 5. Range collections - implicit def rangeHasSeqOps[C <: Range]: HasSeqOps[C] { type A = Int } = - new HasSeqOps[C] { - type A = Int - def apply(c: C): SeqOps[Int, AnyConstr, _] = c - } - -} diff --git a/src/main/scala/scala/collection/decorators/ImmutableMapDecorator.scala b/src/main/scala/scala/collection/decorators/ImmutableMapDecorator.scala deleted file mode 100644 index acf556f..0000000 --- a/src/main/scala/scala/collection/decorators/ImmutableMapDecorator.scala +++ /dev/null @@ -1,40 +0,0 @@ -package scala -package collection -package decorators - -class ImmutableMapDecorator[C, M <: HasImmutableMapOps[C]](coll: C)(implicit val map: M) { - - /** - * Updates an existing binding or create a new one according to the - * result of the application of `f`. - * - * This operation retrieves the current binding for `key` and passes - * it to the partial function `f`. If `f` is not defined, nothing - * is changed on the underlying Map. If `f` returns `Some(v)`, the - * binding is updated with the new value `v`. If `f` returns `None`, - * the binding is removed. - * - * For example, to update an existing binding: - * - * {{{ - * val updatedMap = - * map.updatedWith("foo") { case Some(previous) => Some(previous * 2) } - * }}} - * - * @return A new updated `Map` - */ - def updatedWith[That](key: map.K)(f: PartialFunction[Option[map.V], Option[map.V]])(implicit bf: BuildFrom[C, (map.K, map.V), That]): That = { - val pf = f.lift - val `this` = map(coll) - val previousValue = `this`.get(key) - pf(previousValue) match { - case None => bf.fromSpecificIterable(coll)(`this`.toIterable) - case Some(result) => - result match { - case None => bf.fromSpecificIterable(coll)((`this` - key).toIterable) - case Some(v) => bf.fromSpecificIterable(coll)((`this` + (key -> v)).toIterable) - } - } - } - -} diff --git a/src/main/scala/scala/collection/decorators/IterableDecorator.scala b/src/main/scala/scala/collection/decorators/IterableDecorator.scala index 4582548..579943b 100644 --- a/src/main/scala/scala/collection/decorators/IterableDecorator.scala +++ b/src/main/scala/scala/collection/decorators/IterableDecorator.scala @@ -2,7 +2,9 @@ package scala package collection package decorators -class IterableDecorator[C, I <: HasIterableOps[C]](coll: C)(implicit val it: I) { +import scala.collection.generic.IsIterable + +class IterableDecorator[C, I <: IsIterable[C]](coll: C)(implicit val it: I) { /** * Left to right fold that stops if the combination function `op` diff --git a/src/main/scala/scala/collection/decorators/MapDecorator.scala b/src/main/scala/scala/collection/decorators/MapDecorator.scala index af0425c..cd8de7d 100644 --- a/src/main/scala/scala/collection/decorators/MapDecorator.scala +++ b/src/main/scala/scala/collection/decorators/MapDecorator.scala @@ -1,7 +1,9 @@ package scala.collection package decorators -class MapDecorator[C, M <: HasMapOps[C]](coll: C)(implicit val map: M) { +import scala.collection.generic.IsMap + +class MapDecorator[C, M <: IsMap[C]](coll: C)(implicit val map: M) { /** * Combines entries of `this` Map with entries of `that` Map that have the same key, diff --git a/src/main/scala/scala/collection/decorators/MutableMapDecorator.scala b/src/main/scala/scala/collection/decorators/MutableMapDecorator.scala deleted file mode 100644 index 366087f..0000000 --- a/src/main/scala/scala/collection/decorators/MutableMapDecorator.scala +++ /dev/null @@ -1,43 +0,0 @@ -package scala -package collection -package decorators - -class MutableMapDecorator[K, V](`this`: mutable.Map[K, V]) { - - /** - * Updates an existing binding or create a new one according to the - * result of the application of `f`. - * - * This operation retrieves the current binding for `key` and passes - * it to the partial function `f`. If `f` is not defined, nothing - * is changed on the underlying Map. If `f` returns `Some(v)`, the - * binding is updated with the new value `v`. If `f` returns `None`, - * the binding is removed. - * - * For example, to update an existing binding: - * - * {{{ - * updateWith("foo") { case Some(previous) => Some(previous * 2) } - * }}} - * - * @return The current value associated with `key`, or `None` if the - * there is no such binding or if it has been removed - */ - def updateWith(key: K)(f: PartialFunction[Option[V], Option[V]]): Option[V] = { - val pf = f.lift - val previousValue = `this`.get(key) - pf(previousValue) match { - case None => previousValue - case Some(result) => - result match { - case None => - `this` -= key - None - case Some(v) => - `this`(key) = v - Some(v) - } - } - } - -} \ No newline at end of file diff --git a/src/main/scala/scala/collection/decorators/SeqDecorator.scala b/src/main/scala/scala/collection/decorators/SeqDecorator.scala index 4dce7a2..e5c441a 100644 --- a/src/main/scala/scala/collection/decorators/SeqDecorator.scala +++ b/src/main/scala/scala/collection/decorators/SeqDecorator.scala @@ -1,12 +1,14 @@ package scala.collection package decorators +import scala.collection.generic.IsSeq + /** * @param coll the decorated collection * @param seq evidence that type `C` is a sequence * @tparam C type of the decorated collection (e.g. `List[Int]`, `String`, etc.) */ -class SeqDecorator[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { +class SeqDecorator[C, S <: IsSeq[C]](coll: C)(implicit val seq: S) { /** Adds the element `sep` between each element of the sequence. * If the sequence has less than two elements, the collection is unchanged. @@ -21,7 +23,7 @@ class SeqDecorator[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { * }}} */ def intersperse[B >: seq.A, That](sep: B)(implicit bf: BuildFrom[C, B, That]): That = - bf.fromSpecificIterable(coll)(new View.Intersperse(seq(coll), sep)) + bf.fromSpecific(coll)(new View.Intersperse(seq(coll), sep)) /** Adds the element `sep` between each element of the sequence, * prepending `start` and appending `end`. @@ -39,7 +41,7 @@ class SeqDecorator[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { * }}} */ def intersperse[B >: seq.A, That](start: B, sep: B, end: B)(implicit bf: BuildFrom[C, B, That]): That = - bf.fromSpecificIterable(coll)(new View.IntersperseSurround(seq(coll), start, sep, end)) + bf.fromSpecific(coll)(new View.IntersperseSurround(seq(coll), start, sep, end)) /** Produces a new sequence where all occurrences of some element are replaced by * a different element. @@ -52,5 +54,5 @@ class SeqDecorator[C, S <: HasSeqOps[C]](coll: C)(implicit val seq: S) { * `replacement` */ def replaced[B >: seq.A, That](elem: B, replacement: B)(implicit bf: BuildFrom[C, B, That]): That = - bf.fromSpecificIterable(coll)(new collection.View.Map(seq(coll), (a: seq.A) => if (a == elem) replacement else a)) + bf.fromSpecific(coll)(new collection.View.Map(seq(coll), (a: seq.A) => if (a == elem) replacement else a)) } diff --git a/src/main/scala/scala/collection/decorators/package.scala b/src/main/scala/scala/collection/decorators/package.scala index d76c6cd..9f5511c 100644 --- a/src/main/scala/scala/collection/decorators/package.scala +++ b/src/main/scala/scala/collection/decorators/package.scala @@ -1,5 +1,6 @@ package scala.collection +import scala.collection.generic.{IsIterable, IsMap, IsSeq} import scala.language.implicitConversions package object decorators { @@ -7,19 +8,13 @@ package object decorators { implicit def iteratorDecorator[A](it: Iterator[A]): IteratorDecorator[A] = new IteratorDecorator[A](it) - implicit def IterableDecorator[C](coll: C)(implicit it: HasIterableOps[C]): IterableDecorator[C, it.type] = + implicit def IterableDecorator[C](coll: C)(implicit it: IsIterable[C]): IterableDecorator[C, it.type] = new IterableDecorator(coll)(it) - implicit def SeqDecorator[C](coll: C)(implicit seq: HasSeqOps[C]): SeqDecorator[C, seq.type] = + implicit def SeqDecorator[C](coll: C)(implicit seq: IsSeq[C]): SeqDecorator[C, seq.type] = new SeqDecorator(coll)(seq) - implicit def MapDecorator[C](coll: C)(implicit map: HasMapOps[C]): MapDecorator[C, map.type] = + implicit def MapDecorator[C](coll: C)(implicit map: IsMap[C]): MapDecorator[C, map.type] = new MapDecorator(coll)(map) - implicit def ImmutableMapDecorator[C](coll: C)(implicit map: HasImmutableMapOps[C]): ImmutableMapDecorator[C, map.type] = - new ImmutableMapDecorator(coll)(map) - - implicit def MutableMapDecorator[K, V](map: mutable.Map[K, V]): MutableMapDecorator[K, V] = - new MutableMapDecorator[K, V](map) - } diff --git a/src/main/scala/scala/collection/immutable/MultiDict.scala b/src/main/scala/scala/collection/immutable/MultiDict.scala index 075d037..1a750ae 100644 --- a/src/main/scala/scala/collection/immutable/MultiDict.scala +++ b/src/main/scala/scala/collection/immutable/MultiDict.scala @@ -2,7 +2,6 @@ package scala package collection package immutable -import collection.decorators._ import scala.collection.mutable.{Builder, ImmutableBuilder} /** @@ -18,7 +17,12 @@ class MultiDict[K, V] private (elems: Map[K, Set[V]]) def sets: Map[K, Set[V]] = elems - override def multiMapFactory: MapFactory[MultiDict] = MultiDict + override def multiDictFactory: MapFactory[MultiDict] = MultiDict + override protected def fromSpecific(coll: IterableOnce[(K, V)]): MultiDict[K, V] = multiDictFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(K, V), MultiDict[K, V]] = multiDictFactory.newBuilder[K, V] + override def empty: MultiDict[K, V] = multiDictFactory.empty + override def withFilter(p: ((K, V)) => Boolean): MultiDictOps.WithFilter[K, V, Iterable, MultiDict] = + new MultiDictOps.WithFilter(this, p) /** * @return a new multidict that contains all the entries of this multidict @@ -29,6 +33,7 @@ class MultiDict[K, V] private (elems: Map[K, Set[V]]) case Some(vs) => val updatedVs = vs - value if (updatedVs.nonEmpty) Some(updatedVs) else None + case None => None }) /** Alias for `remove` */ diff --git a/src/main/scala/scala/collection/immutable/MultiSet.scala b/src/main/scala/scala/collection/immutable/MultiSet.scala index 8188617..14d0b80 100644 --- a/src/main/scala/scala/collection/immutable/MultiSet.scala +++ b/src/main/scala/scala/collection/immutable/MultiSet.scala @@ -4,8 +4,6 @@ package immutable import scala.collection.mutable.{Builder, ImmutableBuilder} -import scala.collection.decorators.ImmutableMapDecorator - /** * An immutable multiset * @tparam A the element type of the collection @@ -16,6 +14,10 @@ trait MultiSet[A] with MultiSetOps[A, MultiSet, MultiSet[A]] { override def iterableFactory: IterableFactory[MultiSet] = MultiSet + override protected def fromSpecific(coll: IterableOnce[A]): MultiSet[A] = iterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, MultiSet[A]] = iterableFactory.newBuilder + override def empty: MultiSet[A] = iterableFactory.empty + } trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] extends collection.MultiSetOps[A, CC, C] { @@ -67,6 +69,7 @@ class MultiSetImpl[A] private[immutable] (elems: Map[A, Int]) extends MultiSet[A def excl(elem: A): MultiSet[A] = new MultiSetImpl(elems.updatedWith(elem) { case Some(n) => if (n > 1) Some(n - 1) else None + case None => None }) } diff --git a/src/main/scala/scala/collection/immutable/SortedMultiDict.scala b/src/main/scala/scala/collection/immutable/SortedMultiDict.scala index 8e884d6..08af58f 100644 --- a/src/main/scala/scala/collection/immutable/SortedMultiDict.scala +++ b/src/main/scala/scala/collection/immutable/SortedMultiDict.scala @@ -3,7 +3,6 @@ package collection package immutable import scala.collection.mutable.{Builder, ImmutableBuilder} -import scala.collection.decorators._ /** * An immutable multidict whose keys are sorted @@ -16,9 +15,12 @@ class SortedMultiDict[K, V] private (elems: SortedMap[K, Set[V]])(implicit val o with collection.SortedMultiDictOps[K, V, SortedMultiDict, SortedMultiDict[K, V]] with collection.IterableOps[(K, V), Iterable, SortedMultiDict[K, V]] { - def sortedMultiMapFactory: SortedMapFactory[SortedMultiDict] = SortedMultiDict - - protected[this] def sortedFromIterable[L: Ordering, W](it: collection.Iterable[(L, W)]): SortedMultiDict[L, W] = sortedMultiMapFactory.from(it) + override def sortedMultiDictFactory: SortedMapFactory[SortedMultiDict] = SortedMultiDict + override protected def fromSpecific(coll: IterableOnce[(K, V)]): SortedMultiDict[K, V] = sortedMultiDictFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(K, V), SortedMultiDict[K, V]] = sortedMultiDictFactory.newBuilder[K, V] + override def empty: SortedMultiDict[K, V] = sortedMultiDictFactory.empty + override def withFilter(p: ((K, V)) => Boolean): SortedMultiDictOps.WithFilter[K, V, Iterable, collection.MultiDict, SortedMultiDict] = + new SortedMultiDictOps.WithFilter[K, V, Iterable, collection.MultiDict, SortedMultiDict](this, p) def sets: SortedMap[K, Set[V]] = elems @@ -47,6 +49,7 @@ class SortedMultiDict[K, V] private (elems: SortedMap[K, Set[V]])(implicit val o case Some(vs) => val updatedVs = vs - value if (updatedVs.nonEmpty) Some(updatedVs) else None + case None => None }) /** Alias for `remove` */ diff --git a/src/main/scala/scala/collection/immutable/SortedMultiSet.scala b/src/main/scala/scala/collection/immutable/SortedMultiSet.scala index 742e58a..c1d593f 100644 --- a/src/main/scala/scala/collection/immutable/SortedMultiSet.scala +++ b/src/main/scala/scala/collection/immutable/SortedMultiSet.scala @@ -2,7 +2,6 @@ package scala package collection package immutable -import scala.collection.decorators.ImmutableMapDecorator import scala.collection.mutable.{Builder, ImmutableBuilder} /** @@ -18,8 +17,12 @@ class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering def occurrences: SortedMap[A, Int] = elems - override def iterableFactory: IterableFactory[MultiSet] = MultiSet override def sortedIterableFactory: SortedIterableFactory[SortedMultiSet] = SortedMultiSet + override protected def fromSpecific(coll: IterableOnce[A]): SortedMultiSet[A] = sortedIterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, SortedMultiSet[A]] = sortedIterableFactory.newBuilder[A] + override def empty: SortedMultiSet[A] = sortedIterableFactory.empty + override def withFilter(p: A => Boolean): SortedMultiSetOps.WithFilter[A, MultiSet, SortedMultiSet] = + new SortedMultiSetOps.WithFilter(this, p) def rangeImpl(from: Option[A], until: Option[A]): SortedMultiSet[A] = new SortedMultiSet(elems.rangeImpl(from, until)) @@ -44,6 +47,7 @@ class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering def excl(elem: A): SortedMultiSet[A] = new SortedMultiSet(elems.updatedWith(elem) { case Some(n) => if (n > 1) Some(n - 1) else None + case None => None }) } diff --git a/src/main/scala/scala/collection/mutable/MultiDict.scala b/src/main/scala/scala/collection/mutable/MultiDict.scala index 0ba1c64..c364538 100644 --- a/src/main/scala/scala/collection/mutable/MultiDict.scala +++ b/src/main/scala/scala/collection/mutable/MultiDict.scala @@ -2,8 +2,6 @@ package scala package collection package mutable -import collection.decorators._ - /** * A mutable multidict * @tparam K the type of keys @@ -11,11 +9,19 @@ import collection.decorators._ */ class MultiDict[K, V] private (elems: Map[K, Set[V]]) extends collection.MultiDict[K, V] + with Iterable[(K, V)] + with IterableOps[(K, V), Iterable, MultiDict[K, V]] with collection.MultiDictOps[K, V, MultiDict, MultiDict[K, V]] with Growable[(K, V)] with Shrinkable[(K, V)] { - override def multiMapFactory: MapFactory[MultiDict] = MultiDict + override def multiDictFactory: MapFactory[MultiDict] = MultiDict + override protected def fromSpecific(coll: IterableOnce[(K, V)]): MultiDict[K, V] = multiDictFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(K, V), MultiDict[K, V]] = multiDictFactory.newBuilder[K, V] + override def empty: MultiDict[K, V] = multiDictFactory.empty + override def withFilter(p: ((K, V)) => Boolean): MultiDictOps.WithFilter[K, V, Iterable, MultiDict] = + new MultiDictOps.WithFilter(this, p) + override def knownSize = -1 def sets: collection.Map[K, collection.Set[V]] = elems @@ -34,6 +40,7 @@ class MultiDict[K, V] private (elems: Map[K, Set[V]]) case Some(vs) => vs -= v if (vs.nonEmpty) Some(vs) else None + case None => None } this } diff --git a/src/main/scala/scala/collection/mutable/MultiSet.scala b/src/main/scala/scala/collection/mutable/MultiSet.scala index 2f4c9f9..e2098a8 100644 --- a/src/main/scala/scala/collection/mutable/MultiSet.scala +++ b/src/main/scala/scala/collection/mutable/MultiSet.scala @@ -2,8 +2,6 @@ package scala package collection package mutable -import scala.collection.decorators.MutableMapDecorator - /** * A mutable multiset. */ @@ -14,6 +12,11 @@ trait MultiSet[A] with Shrinkable [A] { override def iterableFactory: IterableFactory[MultiSet] = MultiSet + override protected def fromSpecific(coll: IterableOnce[A]): MultiSet[A] = iterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, MultiSet[A]] = iterableFactory.newBuilder + override def empty: MultiSet[A] = iterableFactory.empty + + override def knownSize = super[Growable].knownSize } class MultiSetImpl[A] private[mutable] (val elems: Map[A, Int]) extends MultiSet[A] { @@ -31,6 +34,7 @@ class MultiSetImpl[A] private[mutable] (val elems: Map[A, Int]) extends MultiSet def subtractOne(elem: A): this.type = { elems.updateWith(elem) { case Some(n) => if (n > 1) Some(n - 1) else None + case None => None } this } diff --git a/src/main/scala/scala/collection/mutable/SortedMultiDict.scala b/src/main/scala/scala/collection/mutable/SortedMultiDict.scala index a32a31d..1d4dcef 100644 --- a/src/main/scala/scala/collection/mutable/SortedMultiDict.scala +++ b/src/main/scala/scala/collection/mutable/SortedMultiDict.scala @@ -2,24 +2,29 @@ package scala package collection package mutable -import scala.collection.decorators._ - /** * A mutable multidict whose keys are sorted * @tparam K the type of keys * @tparam V the type of values */ class SortedMultiDict[K, V] private (elems: SortedMap[K, Set[V]])(implicit val ordering: Ordering[K]) - extends collection.SortedMultiDict[K, V] + extends Iterable[(K, V)] + with collection.SortedMultiDict[K, V] + with IterableOps[(K, V), Iterable, SortedMultiDict[K, V]] with collection.SortedMultiDictOps[K, V, SortedMultiDict, SortedMultiDict[K, V]] with Growable[(K, V)] with Shrinkable[(K, V)] { - def sets: collection.SortedMap[K, collection.Set[V]] = elems + override def knownSize = -1 - def sortedMultiMapFactory: SortedMapFactory[SortedMultiDict] = SortedMultiDict + def sets: collection.SortedMap[K, collection.Set[V]] = elems - protected[this] def sortedFromIterable[L: Ordering, W](it: collection.Iterable[(L, W)]): SortedMultiDict[L, W] = sortedMultiMapFactory.from(it) + override def sortedMultiDictFactory: SortedMapFactory[SortedMultiDict] = SortedMultiDict + override protected def fromSpecific(coll: IterableOnce[(K, V)]): SortedMultiDict[K, V] = sortedMultiDictFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[(K, V), SortedMultiDict[K, V]] = sortedMultiDictFactory.newBuilder[K, V] + override def empty: SortedMultiDict[K, V] = sortedMultiDictFactory.empty + override def withFilter(p: ((K, V)) => Boolean): SortedMultiDictOps.WithFilter[K, V, Iterable, collection.MultiDict, SortedMultiDict] = + new SortedMultiDictOps.WithFilter[K, V, Iterable, collection.MultiDict, SortedMultiDict](this, p) def rangeImpl(from: Option[K], until: Option[K]): SortedMultiDict[K, V] = new SortedMultiDict(elems.rangeImpl(from, until)) @@ -39,6 +44,7 @@ class SortedMultiDict[K, V] private (elems: SortedMap[K, Set[V]])(implicit val o case Some(vs) => vs -= v if (vs.nonEmpty) Some(vs) else None + case None => None } this } diff --git a/src/main/scala/scala/collection/mutable/SortedMultiSet.scala b/src/main/scala/scala/collection/mutable/SortedMultiSet.scala index a1a17fd..1bc1667 100644 --- a/src/main/scala/scala/collection/mutable/SortedMultiSet.scala +++ b/src/main/scala/scala/collection/mutable/SortedMultiSet.scala @@ -2,8 +2,6 @@ package scala package collection package mutable -import scala.collection.decorators.MutableMapDecorator - /** * A mutable multiset whose elements are sorted according to a given ordering. * @@ -20,6 +18,11 @@ class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering def occurrences: collection.SortedMap[A, Int] = elems override def sortedIterableFactory: SortedIterableFactory[SortedMultiSet] = SortedMultiSet + override protected def fromSpecific(coll: IterableOnce[A]): SortedMultiSet[A] = sortedIterableFactory.from(coll) + override protected def newSpecificBuilder: mutable.Builder[A, SortedMultiSet[A]] = sortedIterableFactory.newBuilder[A] + override def empty: SortedMultiSet[A] = sortedIterableFactory.empty + override def withFilter(p: A => Boolean): SortedMultiSetOps.WithFilter[A, MultiSet, SortedMultiSet] = + new SortedMultiSetOps.WithFilter(this, p) def rangeImpl(from: Option[A], until: Option[A]): SortedMultiSet[A] = new SortedMultiSet(elems.rangeImpl(from, until)) @@ -35,6 +38,7 @@ class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering def subtractOne(elem: A): this.type = { elems.updateWith(elem) { case Some(n) => if (n > 1) Some(n - 1) else None + case None => None } this } diff --git a/src/test/scala/scala/collection/decorators/ImmutableMapDecoratorTest.scala b/src/test/scala/scala/collection/decorators/ImmutableMapDecoratorTest.scala deleted file mode 100644 index d3c47b4..0000000 --- a/src/test/scala/scala/collection/decorators/ImmutableMapDecoratorTest.scala +++ /dev/null @@ -1,30 +0,0 @@ -package scala -package collection -package decorators - -import org.junit.{Assert, Test} - -class ImmutableMapDecoratorTest { - - @Test - def updatedWith(): Unit = { - var ms = new MultiSet[String](immutable.Map.empty) - ms -= "foo" - Assert.assertEquals(Map.empty, ms.elems) - ms += "foo" - ms += "bar" - ms += "foo" - Assert.assertEquals(Map("foo" -> 2, "bar" -> 1), ms.elems) - ms -= "foo" - ms -= "bar" - Assert.assertEquals(Map("foo" -> 1), ms.elems) - } - - class MultiSet[A](val elems: immutable.Map[A, Int]) { - def + (elem: A): MultiSet[A] = - new MultiSet(elems.updatedWith(elem) { case Some(n) => Some(n + 1) case None => Some(1) }) - def - (elem: A): MultiSet[A] = - new MultiSet(elems.updatedWith(elem) { case Some(n) => if (n > 1) Some(n - 1) else None }) - } - -} diff --git a/src/test/scala/scala/collection/decorators/MutableMapDecoratorTest.scala b/src/test/scala/scala/collection/decorators/MutableMapDecoratorTest.scala deleted file mode 100644 index f3ab18d..0000000 --- a/src/test/scala/scala/collection/decorators/MutableMapDecoratorTest.scala +++ /dev/null @@ -1,35 +0,0 @@ -package scala -package collection -package decorators - -import org.junit.{Assert, Test} - -class MutableMapDecoratorTest { - - @Test - def updateWith(): Unit = { - val ms = new MultiSet[String] - ms -= "foo" - Assert.assertEquals(Map.empty, ms.elems) - ms += "foo" - ms += "bar" - ms += "foo" - Assert.assertEquals(Map("foo" -> 2, "bar" -> 1), ms.elems) - ms -= "foo" - ms -= "bar" - Assert.assertEquals(Map("foo" -> 1), ms.elems) - } - - class MultiSet[A] { - val elems = mutable.Map.empty[A, Int] - def += (elem: A): this.type = { - elems.updateWith(elem) { case Some(n) => Some(n + 1) case None => Some(1) } - this - } - def -= (elem: A): this.type = { - elems.updateWith(elem) { case Some(n) => if (n > 1) Some(n - 1) else None } - this - } - } - -}