Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.

Commit 2f62c28

Browse files
committed
Add SeqView. Make sure getting a View’s View is a no-op.
1 parent cce4620 commit 2f62c28

File tree

26 files changed

+228
-160
lines changed

26 files changed

+228
-160
lines changed

collections-contrib/src/main/scala/strawman/collection/MultiDict.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
9494
* @tparam W new type of values
9595
*/
9696
def map[L, W](f: ((K, V)) => (L, W)): CC[L, W] =
97-
multiMapFromIterable(View.Map(toIterable, f))
97+
multiMapFromIterable(new View.Map(toIterable, f))
9898

9999
/**
100100
* @return a multidict that contains all the entries of `this` multidict,
@@ -118,19 +118,19 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
118118
*/
119119
def collect[L, W](pf: PartialFunction[(K, V), (L, W)]): CC[L, W] =
120120
flatMap(kv =>
121-
if (pf.isDefinedAt(kv)) View.Single(pf(kv))
121+
if (pf.isDefinedAt(kv)) new View.Single(pf(kv))
122122
else View.Empty
123123
)
124124

125125
/** Concatenate the entries given in `that` iterable to `this` multidict */
126126
def concat(that: Iterable[(K, V)]): C =
127-
fromSpecificIterable(View.Concat(toIterable, that))
127+
fromSpecificIterable(new View.Concat(toIterable, that))
128128

129129
override def withFilter(p: ((K, V)) => Boolean): MultiMapWithFilter = new MultiMapWithFilter(p)
130130

131131
class MultiMapWithFilter(p: ((K, V)) => Boolean) extends WithFilter(p) {
132-
def map[L, W](f: ((K, V)) => (L, W)): CC[L, W] = multiMapFromIterable(View.Map(filtered, f))
133-
def flatMap[L, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = multiMapFromIterable(View.FlatMap(filtered, f))
132+
def map[L, W](f: ((K, V)) => (L, W)): CC[L, W] = multiMapFromIterable(new View.Map(filtered, f))
133+
def flatMap[L, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = multiMapFromIterable(new View.FlatMap(filtered, f))
134134
override def withFilter(q: ((K, V)) => Boolean): MultiMapWithFilter = new MultiMapWithFilter(kv => p(kv) && q(kv))
135135
}
136136

@@ -150,7 +150,7 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
150150
* @tparam W the type of values of the returned multidict
151151
*/
152152
def mapSets[L, W](f: ((K, Set[V])) => (L, Set[W])): CC[L, W] =
153-
fromSets(View.Map(sets, f))
153+
fromSets(new View.Map(sets, f))
154154

155155
/**
156156
* @return a multidict that contains all the entries of `this` multidict,
@@ -163,7 +163,7 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
163163
*/
164164
def collectSets[L, W](pf: PartialFunction[(K, Set[V]), (L, Set[W])]): CC[L, W] =
165165
flatMapSets(kvs =>
166-
if (pf.isDefinedAt(kvs)) View.Single(pf(kvs))
166+
if (pf.isDefinedAt(kvs)) new View.Single(pf(kvs))
167167
else View.Empty
168168
)
169169

@@ -176,7 +176,7 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
176176
* @tparam W the type of values of the returned multidict
177177
*/
178178
def flatMapSets[L, W](f: ((K, Set[V])) => IterableOnce[(L, Set[W])]): CC[L, W] =
179-
fromSets(View.FlatMap(sets, f))
179+
fromSets(new View.FlatMap(sets, f))
180180

181181
/**
182182
* @return a new multidict concatenating the values of this multidict
@@ -185,14 +185,14 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
185185
* @param that the collection of values to add to this multidict
186186
*/
187187
def concatSets(that: Iterable[(K, Set[V])]): C =
188-
fromSpecificSets(View.Concat(sets, that))
188+
fromSpecificSets(new View.Concat(sets, that))
189189

190190
/**
191191
* @return a multidict that contains all the entries of this multidict
192192
* that satisfy the predicate `p`
193193
*/
194194
def filterSets(p: ((K, Set[V])) => Boolean): C =
195-
fromSpecificSets(View.Filter(sets, p, isFlipped = false))
195+
fromSpecificSets(new View.Filter(sets, p, isFlipped = false))
196196

197197
}
198198

collections-contrib/src/main/scala/strawman/collection/MultiSet.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
3535
extends IterableOps[A, CC, C] {
3636

3737
protected[this] def fromSpecificOccurrences(it: Iterable[(A, Int)]): C =
38-
fromSpecificIterable(it.view.flatMap { case (e, n) => View.Fill(n)(e) })
38+
fromSpecificIterable(it.view.flatMap { case (e, n) => new View.Fill(n)(e) })
3939

4040
protected[this] def fromOccurrences[E](it: Iterable[(E, Int)]): CC[E] =
4141
// Note new MultiSet(it.to(Map)) would be more efficient but would also loose duplicates
42-
fromIterable(it.view.flatMap { case (e, n) => View.Fill(n)(e) })
42+
fromIterable(it.view.flatMap { case (e, n) => new View.Fill(n)(e) })
4343

4444
/**
4545
* @return All the elements contained in this multiset and their number of occurrences
4646
*/
4747
def occurrences: Map[A, Int]
4848

4949
def iterator(): Iterator[A] =
50-
occurrences.iterator().flatMap { case (elem, n) => View.Fill(n)(elem) }
50+
occurrences.iterator().flatMap { case (elem, n) => new View.Fill(n)(elem) }
5151

5252
/**
5353
* @return The number of occurrences of `elem` in this multiset
@@ -68,7 +68,7 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
6868
* @param that the collection of elements to add to this multiset
6969
*/
7070
def concat(that: Iterable[A]): C =
71-
fromSpecificIterable(View.Concat(toIterable, that))
71+
fromSpecificIterable(new View.Concat(toIterable, that))
7272

7373
/**
7474
* @return a new multiset summing the occurrences of this multiset
@@ -77,7 +77,7 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
7777
* @param that the collection of occurrences to add to this multiset
7878
*/
7979
def concatOccurrences(that: Iterable[(A, Int)]): C =
80-
fromSpecificOccurrences(View.Concat(occurrences, that))
80+
fromSpecificOccurrences(new View.Concat(occurrences, that))
8181

8282
/**
8383
* @return a new multiset resulting from applying the given function `f`
@@ -87,11 +87,11 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
8787
* @tparam B the element type of the returned collection
8888
*/
8989
def mapOccurrences[B](f: ((A, Int)) => (B, Int)): CC[B] =
90-
fromOccurrences(View.Map(occurrences, f))
90+
fromOccurrences(new View.Map(occurrences, f))
9191

9292
def collectOccurrences[B](pf: PartialFunction[(A, Int), (B, Int)]): CC[B] =
9393
flatMapOccurrences(kvs =>
94-
if (pf.isDefinedAt(kvs)) View.Single(pf(kvs))
94+
if (pf.isDefinedAt(kvs)) new View.Single(pf(kvs))
9595
else View.Empty
9696
)
9797

@@ -103,14 +103,14 @@ trait MultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
103103
* @tparam B the element type of the returned collection
104104
*/
105105
def flatMapOccurrences[B](f: ((A, Int)) => IterableOnce[(B, Int)]): CC[B] =
106-
fromOccurrences(View.FlatMap(occurrences, f))
106+
fromOccurrences(new View.FlatMap(occurrences, f))
107107

108108
/**
109109
* @return a new multiset containing only the occurrences of elements
110110
* of this multiset that satisfy the given predicate `p`
111111
*/
112112
def filterOccurrences(p: ((A, Int)) => Boolean): C =
113-
fromSpecificOccurrences(View.Filter(occurrences, p, isFlipped = false))
113+
fromSpecificOccurrences(new View.Filter(occurrences, p, isFlipped = false))
114114

115115
// TODO Add more multiset operations like union and intersection
116116

collections-contrib/src/main/scala/strawman/collection/SortedMultiDict.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
5151
override def withFilter(p: ((K, V)) => Boolean): SortedMultiMapWithFilter = new SortedMultiMapWithFilter(p)
5252

5353
class SortedMultiMapWithFilter(p: ((K, V)) => Boolean) extends MultiMapWithFilter(p) {
54-
def map[L : Ordering, W](f: ((K, V)) => (L, W)): CC[L, W] = sortedFromIterable(View.Map(filtered, f))
55-
def flatMap[L : Ordering, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = sortedFromIterable(View.FlatMap(filtered, f))
54+
def map[L : Ordering, W](f: ((K, V)) => (L, W)): CC[L, W] = sortedFromIterable(new View.Map(filtered, f))
55+
def flatMap[L : Ordering, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = sortedFromIterable(new View.FlatMap(filtered, f))
5656
override def withFilter(q: ((K, V)) => Boolean): SortedMultiMapWithFilter = new SortedMultiMapWithFilter(kv => p(kv) && q(kv))
5757
}
5858

@@ -64,7 +64,7 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
6464
* @tparam L new type of keys
6565
* @tparam W new type of values
6666
*/
67-
def map[L : Ordering, W](f: ((K, V)) => (L, W)): CC[L, W] = sortedFromIterable(View.Map(toIterable, f))
67+
def map[L : Ordering, W](f: ((K, V)) => (L, W)): CC[L, W] = sortedFromIterable(new View.Map(toIterable, f))
6868

6969
/**
7070
* Builds a new sorted multidict by applying a function to all groups of elements
@@ -75,7 +75,7 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
7575
* `f` to each pair of element and its number of occurrences of this
7676
* sorted multiset and collecting the results.
7777
*/
78-
def mapSets[L : Ordering, W](f: ((K, Set[V])) => (L, Set[W])): CC[L, W] = sortedFromSets(View.Map(sets, f))
78+
def mapSets[L : Ordering, W](f: ((K, Set[V])) => (L, Set[W])): CC[L, W] = sortedFromSets(new View.Map(sets, f))
7979

8080
/**
8181
* @return a sorted multidict that contains all the entries of `this` sorted multidict,
@@ -85,7 +85,7 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
8585
* @tparam L new type of keys
8686
* @tparam W new type of values
8787
*/
88-
def flatMap[L : Ordering, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = sortedFromIterable(View.FlatMap(toIterable, f))
88+
def flatMap[L : Ordering, W](f: ((K, V)) => IterableOnce[(L, W)]): CC[L, W] = sortedFromIterable(new View.FlatMap(toIterable, f))
8989

9090
/**
9191
* @return a new sorted multidict resulting from applying the given function `f`
@@ -95,7 +95,7 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
9595
* @tparam L the new type of keys
9696
* @tparam W the type of values of the returned sorted multidict
9797
*/
98-
def flatMapSets[L : Ordering, W](f: ((K, Set[V])) => IterableOnce[(L, Set[W])]): CC[L, W] = sortedFromSets(View.FlatMap(sets, f))
98+
def flatMapSets[L : Ordering, W](f: ((K, Set[V])) => IterableOnce[(L, Set[W])]): CC[L, W] = sortedFromSets(new View.FlatMap(sets, f))
9999

100100
/**
101101
* @return a sorted multidict that contains all the entries of `this` sorted multidict
@@ -107,7 +107,7 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
107107
* @tparam W new type of values
108108
*/
109109
def collect[L : Ordering, W](pf: PartialFunction[(K, V), (L, W)]): CC[L, W] = flatMap(kv =>
110-
if (pf.isDefinedAt(kv)) View.Single(pf(kv))
110+
if (pf.isDefinedAt(kv)) new View.Single(pf(kv))
111111
else View.Empty
112112
)
113113

@@ -121,7 +121,7 @@ trait SortedMultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K,
121121
* @tparam W the new type of values
122122
*/
123123
def collectSets[L : Ordering, W](pf: PartialFunction[(K, Set[V]), (L, Set[W])]): CC[L, W] = flatMapSets(kv =>
124-
if (pf.isDefinedAt(kv)) View.Single(pf(kv))
124+
if (pf.isDefinedAt(kv)) new View.Single(pf(kv))
125125
else View.Empty
126126
)
127127

collections-contrib/src/main/scala/strawman/collection/SortedMultiSet.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
2222

2323
protected[this] def sortedFromIterable[B : Ordering](it: Iterable[B]): CC[B]
2424
protected[this] def sortedFromOccurrences[B : Ordering](it: Iterable[(B, Int)]): CC[B] =
25-
sortedFromIterable(it.view.flatMap { case (b, n) => View.Fill(n)(b) })
25+
sortedFromIterable(it.view.flatMap { case (b, n) => new View.Fill(n)(b) })
2626

2727
/** `this` sorted multiset upcasted to an unsorted multiset */
2828
def unsorted: MultiSet[A]
@@ -38,7 +38,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
3838
* @param start The lower-bound (inclusive) of the iterator
3939
*/
4040
def iteratorFrom(start: A): Iterator[A] =
41-
occurrences.iteratorFrom(start).flatMap { case (elem, n) => View.Fill(n)(elem) }
41+
occurrences.iteratorFrom(start).flatMap { case (elem, n) => new View.Fill(n)(elem) }
4242

4343
def firstKey: A = occurrences.firstKey
4444
def lastKey: A = occurrences.lastKey
@@ -62,9 +62,9 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
6262
*/
6363
class SortedWithFilter(p: A => Boolean) extends WithFilter(p) {
6464

65-
def map[B : Ordering](f: A => B): CC[B] = sortedIterableFactory.from(View.Map(filtered, f))
65+
def map[B : Ordering](f: A => B): CC[B] = sortedIterableFactory.from(new View.Map(filtered, f))
6666

67-
def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedIterableFactory.from(View.FlatMap(filtered, f))
67+
def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedIterableFactory.from(new View.FlatMap(filtered, f))
6868

6969
override def withFilter(q: A => Boolean): SortedWithFilter = new SortedWithFilter(a => p(a) && q(a))
7070

@@ -77,7 +77,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
7777
* @return a new collection resulting from applying the given function
7878
* `f` to each element of this sorted multiset and collecting the results.
7979
*/
80-
def map[B : Ordering](f: A => B): CC[B] = sortedFromIterable(View.Map(toIterable, f))
80+
def map[B : Ordering](f: A => B): CC[B] = sortedFromIterable(new View.Map(toIterable, f))
8181

8282
/**
8383
* Builds a new sorted multiset by applying a function to all pairs of element and its
@@ -90,7 +90,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
9090
* sorted multiset and collecting the results.
9191
*/
9292
def mapOccurrences[B : Ordering](f: ((A, Int)) => (B, Int)): CC[B] =
93-
sortedFromOccurrences(View.Map(occurrences, f))
93+
sortedFromOccurrences(new View.Map(occurrences, f))
9494

9595
/**
9696
* Builds a new collection by applying a function to all elements of this sorted
@@ -101,7 +101,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
101101
* @return a new collection resulting from applying the given function `f` to
102102
* each element of this sorted multiset and concatenating the results.
103103
*/
104-
def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedFromIterable(View.FlatMap(toIterable, f))
104+
def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedFromIterable(new View.FlatMap(toIterable, f))
105105

106106
/**
107107
* Builds a new collection by applying a function to all pairs of element and
@@ -115,7 +115,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
115115
* multiset and concatenating the results.
116116
*/
117117
def flatMapOccurrences[B : Ordering](f: ((A, Int)) => IterableOnce[(B, Int)]): CC[B] =
118-
sortedFromOccurrences(View.FlatMap(occurrences, f))
118+
sortedFromOccurrences(new View.FlatMap(occurrences, f))
119119

120120
/**
121121
* Returns a sorted multiset formed from this sorted multiset and another iterable
@@ -128,7 +128,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
128128
* is the minimum of the lengths of `this` and `that`
129129
*/
130130
def zip[B](that: Iterable[B])(implicit ev: Ordering[B]): CC[(A @uncheckedVariance, B)] = // sound bcs of VarianceNote
131-
sortedFromIterable(View.Zip(toIterable, that))
131+
sortedFromIterable(new View.Zip(toIterable, that))
132132

133133
/**
134134
* @return a new collection resulting from applying the given partial
@@ -138,7 +138,7 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
138138
* @tparam B the element type of the returned collection
139139
*/
140140
def collect[B : Ordering](pf: PartialFunction[A, B]): CC[B] = flatMap(a =>
141-
if (pf.isDefinedAt(a)) View.Single(pf(a))
141+
if (pf.isDefinedAt(a)) new View.Single(pf(a))
142142
else View.Empty
143143
)
144144

@@ -150,14 +150,14 @@ trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
150150
* @tparam B the element type of the returned collection
151151
*/
152152
def collectOccurrences[B : Ordering](pf: PartialFunction[(A, Int), (B, Int)]): CC[B] = flatMapOccurrences(a =>
153-
if (pf.isDefinedAt(a)) View.Single(pf(a))
153+
if (pf.isDefinedAt(a)) new View.Single(pf(a))
154154
else View.Empty
155155
)
156156

157157
// --- Override return type of methods that returned an unsorted MultiSet
158158

159159
override def zipWithIndex: CC[(A, Int)] =
160-
sortedFromIterable(View.ZipWithIndex(toIterable))
160+
sortedFromIterable(new View.ZipWithIndex(toIterable))
161161

162162
}
163163

collections-contrib/src/main/scala/strawman/collection/decorators/SeqDecorator.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class SeqDecorator[A, CC[X] <: SeqOps[X, CC, _]](`this`: CC[A]) {
2424
* }}}
2525
*/
2626
def intersperse[B >: A](sep: B): CC[B] =
27-
`this`.iterableFactory.from(View.Intersperse(`this`.toIterable, sep))
27+
`this`.iterableFactory.from(new View.Intersperse(`this`.toIterable, sep))
2828

2929
/** Adds the element `sep` between each element of the sequence,
3030
* prepending `start` and appending `end`.
@@ -42,6 +42,6 @@ class SeqDecorator[A, CC[X] <: SeqOps[X, CC, _]](`this`: CC[A]) {
4242
* }}}
4343
*/
4444
def intersperse[B >: A, C](start: B, sep: B, end: B): CC[B] =
45-
`this`.iterableFactory.from(View.IntersperseSurround(`this`.toIterable, start, sep, end))
45+
`this`.iterableFactory.from(new View.IntersperseSurround(`this`.toIterable, start, sep, end))
4646

4747
}

collections-contrib/src/main/scala/strawman/collection/decorators/views.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ package decorators
44
/** Views used by decorators */
55
object View {
66

7-
case class Intersperse[A](underlying: Iterable[A], sep: A) extends View[A] {
7+
class Intersperse[A](underlying: Iterable[A], sep: A) extends View[A] {
88
def iterator(): Iterator[A] = underlying.iterator().intersperse(sep)
99

1010
override def knownSize: Int = if (underlying.knownSize > 0) (2 * underlying.knownSize - 1) else underlying.knownSize
1111
}
1212

13-
case class IntersperseSurround[A](underlying: Iterable[A], start: A, sep: A, end: A) extends View[A] {
13+
class IntersperseSurround[A](underlying: Iterable[A], start: A, sep: A, end: A) extends View[A] {
1414
def iterator(): Iterator[A] = underlying.iterator().intersperse(start, sep, end)
1515

1616
override def knownSize: Int =

0 commit comments

Comments
 (0)