Skip to content

Commit 481a78b

Browse files
authored
Merge pull request scala#7745 from NthPortal/topic/ll-sliding/PR
[bug#11399] Fix LazyList#sliding
2 parents b288ecd + 5c0e4f0 commit 481a78b

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

src/library/scala/collection/immutable/LazyList.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,11 @@ final class LazyList[+A] private(private[this] var lazyState: () => LazyList.Sta
572572
if (knownIsEmpty) LazyList.empty
573573
else super.intersect(that)
574574

575-
// TODO: override to detect cycles
576-
override def distinctBy[B](f: A => B): LazyList[A] = super.distinctBy(f)
575+
@tailrec
576+
private def lengthLteq(len: Int): Boolean =
577+
if (len < 0) false
578+
else if (isEmpty) true
579+
else tail.lengthLteq(len - 1)
577580

578581
override def grouped(size: Int): Iterator[LazyList[A]] = {
579582
require(size > 0, "size must be positive, but was " + size)
@@ -587,11 +590,11 @@ final class LazyList[+A] private(private[this] var lazyState: () => LazyList.Sta
587590

588591
@inline private def lazySlidingImpl(size: Int, step: Int): Iterator[LazyList[A]] =
589592
if (knownIsEmpty) Iterator.empty
590-
else Iterator.empty ++ slidingImpl(size, step) // concat with empty iterator so that `slidingImpl` is lazy
593+
else Iterator.empty ++ slidingImpl(size, step, size - step max 0) // concat with empty iterator so that `slidingImpl` is lazy
591594

592-
private def slidingImpl(size: Int, step: Int): Iterator[LazyList[A]] =
593-
if (isEmpty) Iterator.empty
594-
else Iterator.single(take(size)) ++ drop(step).slidingImpl(size, step)
595+
private def slidingImpl(size: Int, step: Int, minLen: Int): Iterator[LazyList[A]] =
596+
if (lengthLteq(minLen)) Iterator.empty
597+
else Iterator.single(take(size)) ++ drop(step).slidingImpl(size, step, minLen)
595598

596599
override def padTo[B >: A](len: Int, elem: B): LazyList[B] = {
597600
if (len <= 0) this

test/junit/scala/collection/immutable/LazyListLazinessTest.scala

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -460,22 +460,26 @@ class LazyListLazinessTest {
460460
assertLazyAllSkipping(_ forall { _ < 2 }, 3)
461461
}
462462

463-
private def genericSliding_properlyLazy(op: LazyListOp[Iterator[LazyList[Int]]]): Unit = {
464-
assertLazyAll(op)
465-
assertLazyAllSkipping(op andThen { _.hasNext }, 1)
466-
assertLazyAllSkipping(op andThen { _.next().force }, 3)
467-
assertKnownEmptyYields(op)(_ eq Iterator.empty)
463+
private def genericSliding_properlyLazy(op: (LazyList[Int], Int) => Iterator[LazyList[Int]],
464+
skipExtra: Int = 0): Unit = {
465+
val op3 = lazyListOp(op(_, 3))
466+
assertLazyAll(op3)
467+
assertLazyAllSkipping(op3 andThen { _.hasNext }, 1 + skipExtra)
468+
assertLazyAllSkipping(op3 andThen { _.next().force }, 3 + skipExtra)
469+
assertKnownEmptyYields(op3)(_ eq Iterator.empty)
468470
}
469471

470472
@Test
471473
def grouped_properlyLazy(): Unit = {
472-
genericSliding_properlyLazy(_ grouped 3)
474+
genericSliding_properlyLazy(_ grouped _)
473475
}
474476

475477
@Test
476478
def sliding_properlyLazy(): Unit = {
477-
genericSliding_properlyLazy(_ sliding 3)
478-
genericSliding_properlyLazy(_.sliding(3, 2))
479+
genericSliding_properlyLazy(_ sliding _, 2)
480+
genericSliding_properlyLazy(_.sliding(_, 2), 1)
481+
genericSliding_properlyLazy(_.sliding(_, 3))
482+
genericSliding_properlyLazy(_.sliding(_, 4))
479483
}
480484

481485
@Test

0 commit comments

Comments
 (0)