Skip to content

Commit 8cb2bbe

Browse files
committed
Introduce IterableOnceOps as common abstraction for Iterable & Iterator
- Unlike the other Ops types, IterableOnceOps is *not* implemented by IterableOnce but only by Iterator and Iterable. - Fix the hierarchy of MultiSets and SortedMultiSets: The refactoring caused soundness problems to show up that were not reported before. These types now follow the usual diamond pattern where mutable/immutable extends generic and sorted extends unsorted.
1 parent 7163c7b commit 8cb2bbe

File tree

4 files changed

+44
-23
lines changed

4 files changed

+44
-23
lines changed

src/main/scala/strawman/collection/immutable/MultiSet.scala

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,38 @@ import strawman.collection.decorators.ImmutableMapDecorator
1010
* An immutable multiset
1111
* @tparam A the element type of the collection
1212
*/
13-
class MultiSet[A] private (elems: Map[A, Int])
13+
trait MultiSet[A]
1414
extends collection.MultiSet[A]
1515
with Iterable[A]
16-
with collection.MultiSetOps[A, MultiSet, MultiSet[A]] {
16+
with MultiSetOps[A, MultiSet, MultiSet[A]] {
17+
18+
override def iterableFactory: IterableFactory[MultiSet] = MultiSet
19+
}
20+
21+
trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]] extends collection.MultiSetOps[A, CC, C] {
22+
/**
23+
* @return an immutable multiset containing all the elements of this multiset
24+
* and one more occurrence of `elem`
25+
* @param elem the element to add
26+
*/
27+
def incl(elem: A): C
28+
29+
/** Alias for `incl` */
30+
@`inline` final def + (elem: A): C = incl(elem)
31+
32+
/**
33+
* @return an immutable multiset containing all the elements of this multiset
34+
* and one occurrence less of `elem`
35+
*
36+
* @param elem the element to remove
37+
*/
38+
def excl(elem: A): C
39+
40+
/** Alias for `excl` */
41+
@`inline` final def - (elem: A): C = excl(elem)
42+
}
43+
44+
class MultiSetImpl[A] private[immutable] (elems: Map[A, Int]) extends MultiSet[A] {
1745

1846
def occurrences: Map[A, Int] = elems
1947

@@ -25,28 +53,22 @@ class MultiSet[A] private (elems: Map[A, Int])
2553
* @param elem the element to add
2654
*/
2755
def incl(elem: A): MultiSet[A] =
28-
new MultiSet(elems.updatedWith(elem) {
56+
new MultiSetImpl(elems.updatedWith(elem) {
2957
case None => Some(1)
3058
case Some(n) => Some(n + 1)
3159
})
3260

33-
/** Alias for `incl` */
34-
@`inline` final def + (elem: A): MultiSet[A] = incl(elem)
35-
3661
/**
3762
* @return an immutable multiset containing all the elements of this multiset
3863
* and one occurrence less of `elem`
3964
*
4065
* @param elem the element to remove
4166
*/
4267
def excl(elem: A): MultiSet[A] =
43-
new MultiSet(elems.updatedWith(elem) {
68+
new MultiSetImpl(elems.updatedWith(elem) {
4469
case Some(n) => if (n > 1) Some(n - 1) else None
4570
})
4671

47-
/** Alias for `excl` */
48-
@`inline` final def - (elem: A): MultiSet[A] = excl(elem)
49-
5072
}
5173

5274
object MultiSet extends IterableFactory[MultiSet] {
@@ -57,7 +79,7 @@ object MultiSet extends IterableFactory[MultiSet] {
5779
case _ => (newBuilder[A]() ++= source).result()
5880
}
5981

60-
def empty[A] = new MultiSet[A](Map.empty)
82+
def empty[A] = new MultiSetImpl[A](Map.empty)
6183

6284
def newBuilder[A](): Builder[A, MultiSet[A]] =
6385
new ImmutableBuilder[A, MultiSet[A]](empty[A]) {

src/main/scala/strawman/collection/immutable/SortedMultiSet.scala

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import strawman.collection.mutable.{Builder, ImmutableBuilder}
1010
* @tparam A Type of elements
1111
*/
1212
class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering: Ordering[A])
13-
extends collection.SortedMultiSet[A]
14-
with Iterable[A]
13+
extends MultiSet[A]
14+
with collection.SortedMultiSet[A]
15+
with MultiSetOps[A, MultiSet, SortedMultiSet[A]]
1516
with collection.SortedMultiSetOps[A, SortedMultiSet, SortedMultiSet[A]]
1617
with collection.IterableOps[A, MultiSet, SortedMultiSet[A]] {
1718

@@ -34,9 +35,6 @@ class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering
3435
case Some(n) => Some(n + 1)
3536
})
3637

37-
/** Alias for `incl` */
38-
@`inline` final def + (elem: A): SortedMultiSet[A] = incl(elem)
39-
4038
/**
4139
* @return an immutable sorted multiset containing all the elements of
4240
* this multiset and one occurrence less of `elem`
@@ -47,10 +45,6 @@ class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering
4745
new SortedMultiSet(elems.updatedWith(elem) {
4846
case Some(n) => if (n > 1) Some(n - 1) else None
4947
})
50-
51-
/** Alias for `excl` */
52-
@`inline` final def - (elem: A): SortedMultiSet[A] = excl(elem)
53-
5448
}
5549

5650
object SortedMultiSet extends SortedIterableFactory[SortedMultiSet] {

src/main/scala/strawman/collection/mutable/MultiSet.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import strawman.collection.decorators.MutableMapDecorator
77
/**
88
* A mutable multiset.
99
*/
10-
class MultiSet[A] private (val elems: Map[A, Int])
10+
trait MultiSet[A]
1111
extends collection.MultiSet[A]
1212
with collection.MultiSetOps[A, MultiSet, MultiSet[A]]
1313
with Growable[A]
1414
with Shrinkable [A] {
1515

1616
override def iterableFactory: IterableFactory[MultiSet] = MultiSet
17+
}
18+
19+
class MultiSetImpl[A] private[mutable] (val elems: Map[A, Int]) extends MultiSet[A] {
1720

1821
def occurrences: collection.Map[A, Int] = elems
1922

@@ -39,7 +42,7 @@ object MultiSet extends IterableFactory[MultiSet] {
3942

4043
def from[A](source: IterableOnce[A]): MultiSet[A] = (newBuilder[A]() ++= source).result()
4144

42-
def empty[A]: MultiSet[A] = new MultiSet[A](Map.empty)
45+
def empty[A]: MultiSet[A] = new MultiSetImpl[A](Map.empty)
4346

4447
def newBuilder[A](): Builder[A, MultiSet[A]] = new GrowableBuilder[A, MultiSet[A]](empty)
4548

src/main/scala/strawman/collection/mutable/SortedMultiSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import strawman.collection.decorators.MutableMapDecorator
1010
* @tparam A Type of elements
1111
*/
1212
class SortedMultiSet[A] private (elems: SortedMap[A, Int])(implicit val ordering: Ordering[A])
13-
extends collection.SortedMultiSet[A]
13+
extends MultiSet[A]
14+
with collection.SortedMultiSet[A]
1415
with collection.SortedMultiSetOps[A, SortedMultiSet, SortedMultiSet[A]]
16+
with MultiSetOps[A, MultiSet, SortedMultiSet[A]]
1517
with Growable[A]
1618
with Shrinkable[A] {
1719

0 commit comments

Comments
 (0)