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

Commit 3955b6a

Browse files
committed
Take advantage of IndexedViews in IndexedSeqOps
Add IndexedView.Slice Reduce indirection levels by generalizing views to accept XxxOps parameters instead of collection types Add MapView.FilterKeys
1 parent 84027ae commit 3955b6a

File tree

13 files changed

+128
-93
lines changed

13 files changed

+128
-93
lines changed

collections/src/main/scala/strawman/collection/ArrayOps.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ object ArrayOps {
2727
class ArrayOps[A](val xs: Array[A]) extends AnyVal
2828
with IterableOnce[A]
2929
with IndexedSeqOps[A, immutable.IndexedSeq, Array[A]]
30-
with StrictOptimizedSeqOps[A, Seq, Array[A]] {
30+
with StrictOptimizedSeqOps[A, immutable.IndexedSeq, Array[A]] {
3131

3232
protected def fromTaggedIterable[B: ClassTag](coll: Iterable[B]): Array[B] = coll.toArray[B]
3333

@@ -51,7 +51,7 @@ class ArrayOps[A](val xs: Array[A]) extends AnyVal
5151

5252
override def className = "Array"
5353

54-
def map[B: ClassTag](f: A => B): Array[B] = fromTaggedIterable(new View.Map(toIterable, f))
54+
def map[B: ClassTag](f: A => B): Array[B] = fromTaggedIterable(new View.Map(this, f))
5555

5656
def mapInPlace(f: A => A): Array[A] = {
5757
var i = 0
@@ -65,7 +65,7 @@ class ArrayOps[A](val xs: Array[A]) extends AnyVal
6565
def flatMap[B: ClassTag](f: A => IterableOnce[B]): Array[B] = fromTaggedIterable(new View.FlatMap(toIterable, f))
6666

6767
def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] =
68-
fromTaggedIterable(new View.FlatMap(toIterable, (x: A) => asIterable(f(x))))
68+
fromTaggedIterable(new View.FlatMap(this, (x: A) => asIterable(f(x))))
6969

7070
def flatten[B](implicit asIterable: A => strawman.collection.Iterable[B], m: ClassTag[B]): Array[B] = {
7171
val b = WrappedArray.newBuilder[B]().mapResult(_.toArray)
@@ -81,22 +81,22 @@ class ArrayOps[A](val xs: Array[A]) extends AnyVal
8181

8282
@`inline` final def ++[B >: A : ClassTag](xs: Iterable[B]): Array[B] = appendedAll(xs)
8383

84-
def zip[B: ClassTag](that: Iterable[B]): Array[(A, B)] = fromTaggedIterable(new View.Zip(toIterable, that))
84+
def zip[B: ClassTag](that: Iterable[B]): Array[(A, B)] = fromTaggedIterable(new View.Zip(this, that))
8585

86-
def zipWithIndex(implicit ct: ClassTag[(A, Int)]): Array[(A, Int)] = fromTaggedIterable(new View.ZipWithIndex(toIterable))
86+
def zipWithIndex(implicit ct: ClassTag[(A, Int)]): Array[(A, Int)] = fromTaggedIterable(new View.ZipWithIndex(this))
8787

88-
def appended[B >: A : ClassTag](x: B): Array[B] = fromTaggedIterable(new View.Appended(toIterable, x))
88+
def appended[B >: A : ClassTag](x: B): Array[B] = fromTaggedIterable(new View.Appended(this, x))
8989
@`inline` final def :+ [B >: A : ClassTag](x: B): Array[B] = appended(x)
90-
def prepended[B >: A : ClassTag](x: B): Array[B] = fromTaggedIterable(new View.Prepended(x, toIterable))
90+
def prepended[B >: A : ClassTag](x: B): Array[B] = fromTaggedIterable(new View.Prepended(x, this))
9191
@`inline` final def +: [B >: A : ClassTag](x: B): Array[B] = prepended(x)
92-
def prependedAll[B >: A : ClassTag](prefix: Iterable[B]): Array[B] = fromTaggedIterable(new View.Concat(prefix, toIterable))
92+
def prependedAll[B >: A : ClassTag](prefix: Iterable[B]): Array[B] = fromTaggedIterable(new View.Concat(prefix, this))
9393
@`inline` final def ++: [B >: A : ClassTag](prefix: Iterable[B]): Array[B] = prependedAll(prefix)
94-
def appendedAll[B >: A : ClassTag](suffix: Iterable[B]): Array[B] = fromTaggedIterable(new View.Concat(toIterable, suffix))
94+
def appendedAll[B >: A : ClassTag](suffix: Iterable[B]): Array[B] = fromTaggedIterable(new View.Concat(this, suffix))
9595
@`inline` final def :++ [B >: A : ClassTag](suffix: Iterable[B]): Array[B] = appendedAll(suffix)
9696
@`inline` final def concat[B >: A : ClassTag](suffix: Iterable[B]): Array[B] = appendedAll(suffix)
9797

9898
def patch[B >: A : ClassTag](from: Int, other: Iterable[B], replaced: Int): Array[B] =
99-
fromTaggedIterable(new View.Patched(toIterable, from, other, replaced)) //TODO optimize
99+
fromTaggedIterable(new View.Patched(this, from, other, replaced)) //TODO optimize
100100

101101
/** Converts an array of pairs into an array of first elements and an array of second elements.
102102
*

collections/src/main/scala/strawman/collection/IndexedSeq.scala

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,24 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self =>
2929

3030
override def view: IndexedView[A] = new IndexedView.Id[A](this)
3131

32-
override protected[this] def reversed: Iterable[A] = view.reverse
32+
override protected[this] def reversed: Iterable[A] = new IndexedView.Reverse(this)
3333

34-
/** A collection containing the last `n` elements of this collection. */
35-
override def takeRight(n: Int): C = fromSpecificIterable(view.takeRight(n))
34+
// Override transformation operations to use more efficient views than the default ones
35+
override def prepended[B >: A](elem: B): CC[B] = iterableFactory.from(new IndexedView.Prepended(elem, this))
3636

37-
/** The rest of the collection without its `n` last elements. For
38-
* linear, immutable collections this should avoid making a copy. */
39-
override def dropRight(n: Int): C = fromSpecificIterable(view.dropRight(n))
37+
override def take(n: Int): C = fromSpecificIterable(new IndexedView.Take(this, n))
38+
39+
override def takeRight(n: Int): C = fromSpecificIterable(new IndexedView.TakeRight(this, n))
40+
41+
override def drop(n: Int): C = fromSpecificIterable(new IndexedView.Drop(this, n))
42+
43+
override def dropRight(n: Int): C = fromSpecificIterable(new IndexedView.DropRight(this, n))
44+
45+
override def map[B](f: A => B): CC[B] = iterableFactory.from(new IndexedView.Map(this, f))
46+
47+
override def reverse: C = fromSpecificIterable(new IndexedView.Reverse(this))
48+
49+
override def slice(from: Int, until: Int): C = fromSpecificIterable(new IndexedView.Slice(this, from, until))
4050

4151
override def lengthCompare(len: Int): Int = length - len
4252

collections/src/main/scala/strawman/collection/IndexedView.scala

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,45 +27,58 @@ trait IndexedView[+A] extends IndexedSeqOps[A, View, View[A]] with SeqView[A] {
2727
override def dropRight(n: Int): IndexedView[A] = new IndexedView.DropRight(this, n)
2828
override def map[B](f: A => B): IndexedView[B] = new IndexedView.Map(this, f)
2929
override def reverse: IndexedView[A] = new IndexedView.Reverse(this)
30+
override def slice(from: Int, until: Int): IndexedView[A] = new IndexedView.Slice(this, from, until)
3031
}
3132

3233
object IndexedView {
3334

34-
class Id[+A](underlying: IndexedSeqOps[A, AnyConstr, _])
35+
/** An `IndexedSeqOps` whose collection type and collection type constructor are unknown */
36+
type SomeIndexedSeqOps[A] = IndexedSeqOps[A, AnyConstr, _]
37+
38+
class Id[+A](underlying: SomeIndexedSeqOps[A])
3539
extends SeqView.Id(underlying) with IndexedView[A]
3640

37-
class Prepended[+A](elem: A, underlying: Iterable[A] with IndexedSeqOps[A, AnyConstr, _])
41+
class Prepended[+A](elem: A, underlying: SomeIndexedSeqOps[A])
3842
extends SeqView.Prepended(elem, underlying) with IndexedView[A]
3943

40-
class Take[A](underlying: IndexedView[A], n: Int)
44+
class Take[A](underlying: SomeIndexedSeqOps[A], n: Int)
4145
extends SeqView.Take(underlying, n) with IndexedView[A]
4246

43-
class TakeRight[A](underlying: IndexedView[A], n: Int) extends IndexedView[A] {
47+
class TakeRight[A](underlying: SomeIndexedSeqOps[A], n: Int) extends IndexedView[A] {
4448
private[this] val delta = (underlying.size - (n max 0)) max 0
4549
def length = underlying.size - delta
4650
@throws[IndexOutOfBoundsException]
4751
def apply(i: Int) = underlying.apply(i + delta)
4852
}
4953

50-
class Drop[A](underlying: IndexedView[A], n: Int) extends View.Drop[A](underlying, n) with IndexedView[A] {
54+
class Drop[A](underlying: SomeIndexedSeqOps[A], n: Int) extends View.Drop[A](underlying, n) with IndexedView[A] {
5155
def length = (underlying.size - normN) max 0
5256
@throws[IndexOutOfBoundsException]
5357
def apply(i: Int) = underlying.apply(i + normN)
5458
}
5559

56-
class DropRight[A](underlying: IndexedView[A], n: Int) extends IndexedView[A] {
60+
class DropRight[A](underlying: SomeIndexedSeqOps[A], n: Int) extends IndexedView[A] {
5761
private[this] val len = (underlying.size - (n max 0)) max 0
5862
def length = len
5963
@throws[IndexOutOfBoundsException]
6064
def apply(i: Int) = underlying.apply(i)
6165
}
6266

63-
class Map[A, B](underlying: IndexedView[A], f: A => B)
67+
class Map[A, B](underlying: SomeIndexedSeqOps[A], f: A => B)
6468
extends SeqView.Map(underlying, f) with IndexedView[B]
6569

66-
class Reverse[A](underlying: IndexedView[A]) extends IndexedView[A] {
70+
class Reverse[A](underlying: SomeIndexedSeqOps[A]) extends IndexedView[A] {
6771
def length = underlying.size
6872
@throws[IndexOutOfBoundsException]
6973
def apply(i: Int) = underlying.apply(size - 1 - i)
7074
}
75+
76+
class Slice[A](underlying: SomeIndexedSeqOps[A], from: Int, until: Int) extends IndexedView[A] {
77+
protected val lo = from max 0
78+
protected val hi = until min underlying.length
79+
protected val len = (hi - lo) max 0
80+
@throws[IndexOutOfBoundsException]
81+
def apply(i: Int): A = underlying(lo + i)
82+
def length: Int = len
83+
}
7184
}

collections/src/main/scala/strawman/collection/Iterable.scala

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
8484
protected[this] def fromSpecificIterable(coll: Iterable[A]): C
8585

8686
/** Similar to `fromSpecificIterable`, but for a (possibly) different type of element.
87-
* Note that the return type is know `CC[E]`.
87+
* Note that the return type is now `CC[E]`.
8888
*/
8989
@`inline` final protected[this] def fromIterable[E](it: Iterable[E]): CC[E] = iterableFactory.from(it)
9090

@@ -711,15 +711,15 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
711711
* @return a new $coll consisting of all elements of this $coll that satisfy the given
712712
* predicate `pred`. Their order may not be preserved.
713713
*/
714-
def filter(pred: A => Boolean): C = fromSpecificIterable(new View.Filter(toIterable, pred, isFlipped = false))
714+
def filter(pred: A => Boolean): C = fromSpecificIterable(new View.Filter(this, pred, isFlipped = false))
715715

716716
/** Selects all elements of this $coll which do not satisfy a predicate.
717717
*
718718
* @param pred the predicate used to test elements.
719719
* @return a new $coll consisting of all elements of this $coll that do not satisfy the given
720720
* predicate `pred`. Their order may not be preserved.
721721
*/
722-
def filterNot(pred: A => Boolean): C = fromSpecificIterable(new View.Filter(toIterable, pred, isFlipped = true))
722+
def filterNot(pred: A => Boolean): C = fromSpecificIterable(new View.Filter(this, pred, isFlipped = true))
723723

724724
/** Creates a non-strict filter of this $coll.
725725
*
@@ -744,7 +744,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
744744
*/
745745
class WithFilter(p: A => Boolean) extends collection.WithFilter[A, CC] {
746746

747-
protected[this] def filtered = new View.Filter(toIterable, p, isFlipped = false)
747+
protected[this] def filtered = new View.Filter(IterableOps.this, p, isFlipped = false)
748748

749749
def map[B](f: A => B): CC[B] = iterableFactory.from(new View.Map(filtered, f))
750750

@@ -764,7 +764,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
764764
* which requires only a single traversal.
765765
*/
766766
def partition(p: A => Boolean): (C, C) = {
767-
val pn = new View.Partition(toIterable, p)
767+
val pn = new View.Partition(this, p)
768768
(fromSpecificIterable(pn.first), fromSpecificIterable(pn.second))
769769
}
770770

@@ -780,7 +780,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
780780
def splitAt(n: Int): (C, C) = (take(n), drop(n))
781781

782782
/** A collection containing the first `n` elements of this collection. */
783-
def take(n: Int): C = fromSpecificIterable(new View.Take(toIterable, n))
783+
def take(n: Int): C = fromSpecificIterable(new View.Take(this, n))
784784

785785
/** A collection containing the last `n` elements of this collection. */
786786
def takeRight(n: Int): C = {
@@ -802,7 +802,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
802802
* @return the longest prefix of this $coll whose elements all satisfy
803803
* the predicate `p`.
804804
*/
805-
def takeWhile(p: A => Boolean): C = fromSpecificIterable(new View.TakeWhile(toIterable, p))
805+
def takeWhile(p: A => Boolean): C = fromSpecificIterable(new View.TakeWhile(this, p))
806806

807807
/** Splits this $coll into a prefix/suffix pair according to a predicate.
808808
*
@@ -820,7 +820,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
820820
/** The rest of the collection without its `n` first elements. For
821821
* linear, immutable collections this should avoid making a copy.
822822
*/
823-
def drop(n: Int): C = fromSpecificIterable(new View.Drop(toIterable, n))
823+
def drop(n: Int): C = fromSpecificIterable(new View.Drop(this, n))
824824

825825
/** The rest of the collection without its `n` last elements. For
826826
* linear, immutable collections this should avoid making a copy.
@@ -843,7 +843,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
843843
* @return the longest suffix of this $coll whose first element
844844
* does not satisfy the predicate `p`.
845845
*/
846-
def dropWhile(p: A => Boolean): C = fromSpecificIterable(new View.DropWhile(toIterable, p))
846+
def dropWhile(p: A => Boolean): C = fromSpecificIterable(new View.DropWhile(this, p))
847847

848848
/** Partitions elements in fixed size ${coll}s.
849849
* @see [[scala.collection.Iterator]], method `grouped`
@@ -907,7 +907,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
907907
* of this $coll.
908908
*/
909909
def slice(from: Int, until: Int): C =
910-
fromSpecificIterable(new View.Drop(new View.Take(toIterable, until), from))
910+
fromSpecificIterable(new View.Drop(new View.Take(this, until), from))
911911

912912
/** Partitions this $coll into a map of ${coll}s according to some discriminator function.
913913
*
@@ -1022,7 +1022,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
10221022
* @param op the binary operator applied to the intermediate result and the element
10231023
* @return collection with intermediate results
10241024
*/
1025-
def scanLeft[B](z: B)(op: (B, A) => B): CC[B] = fromIterable(new View.ScanLeft(toIterable, z, op))
1025+
def scanLeft[B](z: B)(op: (B, A) => B): CC[B] = fromIterable(new View.ScanLeft(this, z, op))
10261026

10271027
/** Produces a collection containing cumulative results of applying the operator going right to left.
10281028
* The head of the collection is the last cumulative result.
@@ -1056,7 +1056,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
10561056
* @return a new $coll resulting from applying the given function
10571057
* `f` to each element of this $coll and collecting the results.
10581058
*/
1059-
def map[B](f: A => B): CC[B] = fromIterable(new View.Map(toIterable, f))
1059+
def map[B](f: A => B): CC[B] = fromIterable(new View.Map(this, f))
10601060

10611061
/** Builds a new collection by applying a function to all elements of this $coll
10621062
* and using the elements of the resulting collections.
@@ -1089,7 +1089,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
10891089
* @return a new $coll resulting from applying the given collection-valued function
10901090
* `f` to each element of this $coll and concatenating the results.
10911091
*/
1092-
def flatMap[B](f: A => IterableOnce[B]): CC[B] = fromIterable(new View.FlatMap(toIterable, f))
1092+
def flatMap[B](f: A => IterableOnce[B]): CC[B] = fromIterable(new View.FlatMap(this, f))
10931093

10941094
/** Converts this $coll of traversable collections into
10951095
* a $coll formed by the elements of these traversable
@@ -1119,7 +1119,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
11191119
*
11201120
*/
11211121
def flatten[B](implicit asIterable: A => IterableOnce[B]): CC[B] =
1122-
fromIterable(new View.FlatMap(toIterable, asIterable))
1122+
fromIterable(new View.FlatMap(this, asIterable))
11231123

11241124
/** Builds a new collection by applying a partial function to all elements of this $coll
11251125
* on which the function is defined.
@@ -1159,7 +1159,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
11591159
* @return a new $coll which contains all elements
11601160
* of this $coll followed by all elements of `suffix`.
11611161
*/
1162-
def concat[B >: A](suffix: Iterable[B]): CC[B] = fromIterable(new View.Concat(toIterable, suffix))
1162+
def concat[B >: A](suffix: Iterable[B]): CC[B] = fromIterable(new View.Concat(this, suffix))
11631163

11641164
/** Alias for `concat` */
11651165
@`inline` final def ++ [B >: A](suffix: Iterable[B]): CC[B] = concat(suffix)
@@ -1173,7 +1173,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
11731173
* @return a new $coll containing pairs consisting of corresponding elements of this $coll and `that`.
11741174
* The length of the returned collection is the minimum of the lengths of this $coll and `that`.
11751175
*/
1176-
def zip[B](that: Iterable[B]): CC[(A @uncheckedVariance, B)] = fromIterable(new View.Zip(toIterable, that))
1176+
def zip[B](that: Iterable[B]): CC[(A @uncheckedVariance, B)] = fromIterable(new View.Zip(this, that))
11771177
// sound bcs of VarianceNote
11781178

11791179
/** Zips this $coll with its indices.
@@ -1183,7 +1183,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
11831183
* @example
11841184
* `List("a", "b", "c").zipWithIndex == List(("a", 0), ("b", 1), ("c", 2))`
11851185
*/
1186-
def zipWithIndex: CC[(A @uncheckedVariance, Int)] = fromIterable(new View.ZipWithIndex(toIterable))
1186+
def zipWithIndex: CC[(A @uncheckedVariance, Int)] = fromIterable(new View.ZipWithIndex(this))
11871187

11881188
/** Returns a $coll formed from this $coll and another iterable collection
11891189
* by combining corresponding elements in pairs.
@@ -1199,7 +1199,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
11991199
* If this $coll is shorter than `that`, `thisElem` values are used to pad the result.
12001200
* If `that` is shorter than this $coll, `thatElem` values are used to pad the result.
12011201
*/
1202-
def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): CC[(A1, B)] = fromIterable(new View.ZipAll(toIterable, that, thisElem, thatElem))
1202+
def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): CC[(A1, B)] = fromIterable(new View.ZipAll(this, that, thisElem, thatElem))
12031203

12041204
/** Converts this $coll of pairs into two collections of the first and second
12051205
* half of each pair.
@@ -1221,7 +1221,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] {
12211221
* half of each element pair of this $coll.
12221222
*/
12231223
def unzip[A1, A2](implicit asPair: A => (A1, A2)): (CC[A1], CC[A2]) = {
1224-
val unzipped = new View.Unzip(toIterable)
1224+
val unzipped = new View.Unzip(this)
12251225
(fromIterable(unzipped.first), fromIterable(unzipped.second))
12261226
}
12271227

collections/src/main/scala/strawman/collection/Map.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C]
158158
* @return an immutable map consisting only of those key value pairs of this map where the key satisfies
159159
* the predicate `p`. The resulting map wraps the original map without copying any elements.
160160
*/
161-
def filterKeys(p: K => Boolean): View[(K, V)] = new View.FilterKeys(toIterable, p)
161+
def filterKeys(p: K => Boolean): MapView[K, V] = new MapView.FilterKeys(this, p)
162162

163163
/** Transforms this map by applying a function to every retrieved value.
164164
* @param f the function used to transform values of this map.

0 commit comments

Comments
 (0)