Skip to content

Commit 7829ae7

Browse files
authored
Merge pull request scala/scala#9234 from NthPortal/topic/SeqView-Sorted-eager
Make SeqView.Sorted slightly less lazy
2 parents f245d83 + c12fa5a commit 7829ae7

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

library/src/scala/collection/SeqView.scala

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,33 +122,40 @@ object SeqView {
122122
}
123123

124124
@SerialVersionUID(3L)
125-
class Sorted[A, B >: A](private[this] var underlying: SomeSeqOps[A], ord: Ordering[B]) extends SeqView[A] {
125+
class Sorted[A, B >: A] private (private[this] var underlying: SomeSeqOps[A],
126+
private[this] val len: Int,
127+
ord: Ordering[B])
128+
extends SeqView[A] {
126129
outer =>
127130

131+
// force evaluation immediately by calling `length` so infinite collections
132+
// hang on `sorted`/`sortWith`/`sortBy` rather than on arbitrary method calls
133+
def this(underlying: SomeSeqOps[A], ord: Ordering[B]) = this(underlying, underlying.length, ord)
134+
128135
@SerialVersionUID(3L)
129136
private[this] class ReverseSorted extends SeqView[A] {
130137
private[this] lazy val _reversed = new SeqView.Reverse(_sorted)
131138

132139
def apply(i: Int): A = _reversed.apply(i)
133-
def length: Int = elems.length
140+
def length: Int = len
134141
def iterator: Iterator[A] = Iterator.empty ++ _reversed.iterator // very lazy
135-
override def knownSize: Int = elems.knownSize
136-
override def isEmpty: Boolean = elems.isEmpty
142+
override def knownSize: Int = len
143+
override def isEmpty: Boolean = len == 0
137144
override def to[C1](factory: Factory[A, C1]): C1 = _reversed.to(factory)
138145
override def reverse: SeqView[A] = outer
139146
override protected def reversed: Iterable[A] = outer
140147

141148
override def sorted[B1 >: A](implicit ord1: Ordering[B1]): SeqView[A] =
142149
if (ord1 == Sorted.this.ord) outer
143150
else if (ord1.isReverseOf(Sorted.this.ord)) this
144-
else new Sorted(elems, ord1)
151+
else new Sorted(elems, len, ord1)
145152
}
146153

147154
@volatile private[this] var evaluated = false
148155

149156
private[this] lazy val _sorted: Seq[A] = {
150157
val res = {
151-
val len = underlying.length
158+
val len = this.len
152159
if (len == 0) Nil
153160
else if (len == 1) List(underlying.head)
154161
else {
@@ -177,10 +184,10 @@ object SeqView {
177184
}
178185

179186
def apply(i: Int): A = _sorted.apply(i)
180-
def length: Int = elems.length
187+
def length: Int = len
181188
def iterator: Iterator[A] = Iterator.empty ++ _sorted.iterator // very lazy
182-
override def knownSize: Int = elems.knownSize
183-
override def isEmpty: Boolean = elems.isEmpty
189+
override def knownSize: Int = len
190+
override def isEmpty: Boolean = len == 0
184191
override def to[C1](factory: Factory[A, C1]): C1 = _sorted.to(factory)
185192
override def reverse: SeqView[A] = new ReverseSorted
186193
// we know `_sorted` is either tiny or has efficient random access,
@@ -190,7 +197,7 @@ object SeqView {
190197
override def sorted[B1 >: A](implicit ord1: Ordering[B1]): SeqView[A] =
191198
if (ord1 == this.ord) this
192199
else if (ord1.isReverseOf(this.ord)) reverse
193-
else new Sorted(elems, ord1)
200+
else new Sorted(elems, len, ord1)
194201
}
195202
}
196203

0 commit comments

Comments
 (0)