Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ae50ed3

Browse files
committed
Add missing methods to Iterator
1 parent 874bf03 commit ae50ed3

File tree

7 files changed

+130
-22
lines changed

7 files changed

+130
-22
lines changed

src/library/scala/collection/Iterable.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
140140
@deprecated("Use toIterable instead", "2.13.0")
141141
final def toTraversable: Traversable[A] = toIterable
142142

143+
override def isTraversableAgain: Boolean = true
144+
143145
/**
144146
* @return This collection as a `C`.
145147
*/
@@ -223,9 +225,6 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
223225
*/
224226
def lastOption: Option[A] = if (isEmpty) None else Some(last)
225227

226-
@deprecated("Use .knownSize >=0 instead of .hasDefiniteSize", "2.13.0")
227-
@`inline` final def hasDefiniteSize = knownSize >= 0
228-
229228
/** A view over the elements of this collection. */
230229
def view: View[A] = View.fromIteratorProvider(() => iterator)
231230

@@ -309,7 +308,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
309308
*/
310309
def withFilter(p: A => Boolean): collection.WithFilter[A, CC] = new IterableOps.WithFilter(this, p)
311310

312-
/** A pair of, first, all elements that satisfy prediacte `p` and, second,
311+
/** A pair of, first, all elements that satisfy predicate `p` and, second,
313312
* all elements that do not. Interesting because it splits a collection in two.
314313
*
315314
* The default implementation provided here needs to traverse the collection twice.

src/library/scala/collection/IterableOnce.scala

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package collection
33

44
import scala.language.{higherKinds, implicitConversions}
55
import scala.annotation.unchecked.uncheckedVariance
6-
import scala.math.{Ordering, Numeric}
6+
import scala.math.{Numeric, Ordering}
77
import scala.reflect.ClassTag
88
import scala.collection.mutable.StringBuilder
99

@@ -357,6 +357,16 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
357357
*/
358358
def knownSize: Int = -1
359359

360+
@deprecated("Use .knownSize >=0 instead of .hasDefiniteSize", "2.13.0")
361+
@`inline` final def hasDefiniteSize = knownSize >= 0
362+
363+
/** Tests whether this $coll can be repeatedly traversed. Always
364+
* true for Iterables and false for Iterators unless overridden.
365+
*
366+
* @return `true` if it is repeatedly traversable, `false` otherwise.
367+
*/
368+
def isTraversableAgain: Boolean = false
369+
360370
/** Apply `f` to each element for its side effects
361371
* Note: [U] parameter needed to help scalac's type inference.
362372
*/
@@ -627,6 +637,22 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
627637
@deprecated("Use `dest ++= coll` instead", "2.13.0")
628638
@inline final def copyToBuffer[B >: A](dest: mutable.Buffer[B]): Unit = dest ++= this
629639

640+
/** Copy elements to an array.
641+
*
642+
* Fills the given array `xs` starting at index `start` with values of this $coll.
643+
*
644+
* Copying will stop once either all the elements of this $coll have been copied,
645+
* or the end of the array is reached.
646+
*
647+
* @param xs the array to fill.
648+
* @tparam B the type of the elements of the array.
649+
*
650+
* @usecase def copyToArray(xs: Array[A]): Unit
651+
*
652+
* $willNotTerminateInf
653+
*/
654+
def copyToArray[B >: A](xs: Array[B]): xs.type = copyToArray(xs, 0)
655+
630656
/** Copy elements to an array.
631657
*
632658
* Fills the given array `xs` starting at index `start` with values of this $coll.
@@ -642,7 +668,8 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
642668
*
643669
* $willNotTerminateInf
644670
*/
645-
def copyToArray[B >: A](xs: Array[B], start: Int = 0): xs.type = {
671+
672+
def copyToArray[B >: A](xs: Array[B], start: Int): xs.type = {
646673
val xsLen = xs.length
647674
val it = iterator
648675
var i = start
@@ -914,7 +941,9 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
914941
def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = {
915942
// Presumably the fastest way to get in and out of a partial function is for a sentinel function to return itself
916943
// (Tested to be lower-overhead than runWith. Would be better yet to not need to (formally) allocate it)
917-
val sentinel: scala.Function1[A, Any] = new scala.runtime.AbstractFunction1[A, Any]{ def apply(a: A) = this }
944+
val sentinel: scala.Function1[A, Any] = new scala.runtime.AbstractFunction1[A, Any] {
945+
def apply(a: A) = this
946+
}
918947
val it = iterator
919948
while (it.hasNext) {
920949
val x = pf.applyOrElse(it.next(), sentinel)
@@ -923,6 +952,30 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
923952
None
924953
}
925954

955+
@deprecated("`aggregate` is not relevant for sequential collections. Use `foldLeft(z)(seqop)` instead.", "2.13.0")
956+
def aggregate[B](z: => B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)
957+
958+
/** Tests whether every element of this collection's iterator relates to the
959+
* corresponding element of another collection by satisfying a test predicate.
960+
*
961+
* @param that the other collection
962+
* @param p the test predicate, which relates elements from both collections
963+
* @tparam B the type of the elements of `that`
964+
* @return `true` if both collections have the same length and
965+
* `p(x, y)` is `true` for all corresponding elements `x` of this iterator
966+
* and `y` of `that`, otherwise `false`
967+
*/
968+
def corresponds[B](that: IterableOnce[B])(p: (A, B) => Boolean): Boolean = {
969+
val a = iterator
970+
val b = that.iterator
971+
972+
while (a.hasNext && b.hasNext) {
973+
if (!p(a.next(), b.next())) return false
974+
}
975+
976+
a.hasNext == b.hasNext
977+
}
978+
926979
/** Displays all elements of this $coll in a string using start, end, and
927980
* separator strings.
928981
*

src/library/scala/collection/Iterator.scala

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,47 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite
267267
}
268268
}
269269

270+
/** A copy of this $coll with an element value appended until a given target length is reached.
271+
*
272+
* @param len the target length
273+
* @param elem the padding value
274+
* @tparam B the element type of the returned $coll.
275+
* @return a new $coll consisting of
276+
* all elements of this $coll followed by the minimal number of occurrences of `elem` so
277+
* that the resulting collection has a length of at least `len`.
278+
*/
279+
def padTo[B >: A](len: Int, elem: B): Iterator[B] = {
280+
val it = this
281+
new AbstractIterator[B] {
282+
private[this] var i = 0
283+
284+
def next(): B = {
285+
val b =
286+
if (it.hasNext) it.next()
287+
else if (i < len) elem
288+
else Iterator.empty.next()
289+
i += 1
290+
b
291+
}
292+
293+
def hasNext: Boolean = it.hasNext || i < len
294+
}
295+
}
296+
297+
/** Partitions this iterator in two iterators according to a predicate.
298+
*
299+
* @param p the predicate on which to partition
300+
* @return a pair of iterators: the iterator that satisfies the predicate
301+
* `p` and the iterator that does not.
302+
* The relative order of the elements in the resulting iterators
303+
* is the same as in the original iterator.
304+
* @note Reuse: $consumesOneAndProducesTwoIterators
305+
*/
306+
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
307+
val (a, b) = duplicate
308+
(a filter p, b filterNot p)
309+
}
310+
270311
/** Returns an iterator which groups this iterator into fixed size
271312
* blocks. Example usages:
272313
* {{{
@@ -341,6 +382,9 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite
341382
def hasNext: Boolean = current.hasNext
342383
}
343384

385+
@deprecated("Call scanRight on an Iterable instead.", "2.13.0")
386+
def scanRight[B](z: B)(op: (A, B) => B): Iterator[B] = ArrayBuffer.from(this).scanRight(z)(op).iterator
387+
344388
def indexWhere(p: A => Boolean, from: Int = 0): Int = {
345389
var i = math.max(from, 0)
346390
drop(from)

src/library/scala/collection/View.scala

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -310,19 +310,8 @@ object View extends IterableFactory[View] {
310310

311311
@SerialVersionUID(3L)
312312
class PadTo[A](underlying: SomeIterableOps[A], len: Int, elem: A) extends AbstractView[A] {
313-
def iterator: Iterator[A] = new AbstractIterator[A] {
314-
private[this] var i = 0
315-
private[this] val it = underlying.iterator
316-
def next(): A = {
317-
val a =
318-
if (it.hasNext) it.next()
319-
else if (i < len) elem
320-
else Iterator.empty.next()
321-
i += 1
322-
a
323-
}
324-
def hasNext: Boolean = it.hasNext || i < len
325-
}
313+
def iterator: Iterator[A] = underlying.iterator.padTo(len, elem)
314+
326315
override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize max len else -1
327316
}
328317

src/library/scala/collection/mutable/ArrayBuffer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int)
152152

153153
override protected[this] def stringPrefix = "ArrayBuffer"
154154

155-
override def copyToArray[B >: A](xs: Array[B], start: Int = 0): xs.type = copyToArray[B](xs, start, length)
155+
override def copyToArray[B >: A](xs: Array[B], start: Int): xs.type = copyToArray[B](xs, start, length)
156156

157157
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): xs.type = {
158158
val l = scala.math.min(scala.math.min(len, length), xs.length-start)

src/library/scala/collection/mutable/ArraySeq.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ abstract class ArraySeq[T]
6060
/** Clones this object, including the underlying Array. */
6161
override def clone(): ArraySeq[T] = ArraySeq.make(array.clone()).asInstanceOf[ArraySeq[T]]
6262

63-
override def copyToArray[B >: T](xs: Array[B], start: Int = 0): xs.type = copyToArray[B](xs, start, length)
63+
override def copyToArray[B >: T](xs: Array[B], start: Int): xs.type = copyToArray[B](xs, start, length)
6464

6565
override def copyToArray[B >: T](xs: Array[B], start: Int, len: Int): xs.type = {
6666
val l = scala.math.min(scala.math.min(len, length), xs.length-start)

test/junit/scala/collection/IteratorTest.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,29 @@ class IteratorTest {
404404
assertSame(Iterator.empty, iteratorBuilder.result())
405405
}
406406

407+
@Test def partition: Unit = {
408+
val it = Iterator(1, 2, 3, 4, 5, 6, 7)
409+
val (even, odd) = it.partition(n => (n & 1) == 0)
410+
assertSameElements(List.from(even), List(2, 4, 6))
411+
assertSameElements(List.from(odd), List(1, 3, 5, 7))
412+
}
413+
414+
@Test def padTo: Unit = {
415+
val it = Iterator(2, 4, 6, 8)
416+
val padded = it.padTo(7, 10)
417+
assertSameElements(List.from(padded), List(2, 4, 6, 8, 10, 10, 10))
418+
}
419+
420+
@Test def corresponds: Unit = {
421+
val it = Iterator(1, 2, 3, 4, 5)
422+
assertTrue(it.corresponds(Seq(1, 4, 9, 16, 25)) { (a, b) => b == a*a })
423+
}
424+
425+
@Test def aggregate: Unit = {
426+
val result = Iterator('a', 'b', 'c').aggregate(0)({ (sum, ch) => sum + ch.toInt }, { (p1, p2) => p1 + p2 })
427+
assertEquals(result, 294)
428+
}
429+
407430
@Test def copyToArray(): Unit = {
408431
def check(a: Array[Int], start: Int, end: Int) = {
409432
var i = 0

0 commit comments

Comments
 (0)