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

Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/library/scala/collection/immutable/LazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,19 @@ object LazyList extends SeqFactory[LazyList] {
at(0)
}

override def range[A: Integral](start: A, end: A): LazyList[A] =
newLL(rangeImpl(start, end, step = Integral[A].one))

override def range[A](start: A, end: A, step: A)(implicit ev: Integral[A]): LazyList[A] =
newLL {
if (ev.equiv(step, ev.zero)) throw new IllegalArgumentException("step cannot be 0.")
else rangeImpl(start, end, step)
}

private[this] def rangeImpl[A](start: A, end: A, step: A)(implicit ev: Integral[A]): State[A] =
if (ev.lt(start, end)) sCons(start, newLL(rangeImpl(ev.plus(start, step), end, step)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uhm, wait, this does not allow reversed ranges, does it? Like LazyList.range(start = 100, end = 0, step = -2)
I guess rather than check for lt we have to check for !ev.equiv(start, end)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this made me think. This could be a good way to test this without a CPU trap. We just request the reversed range and then we can indeed ask for the head and check it is bigger than Int.MaxValue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, the check is incorrect, hmm. probably need to check the sign or something as well. I'll have another look shortly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my thought is to check the sign of step in the 3 parameter overload of range, and then pass it as a Boolean parameter (probably named positiveStep) to rangeImpl, thus checking the condition only once rather than for each element

Copy link
Contributor Author

@BalmungSan BalmungSan Apr 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed an implementation that allows for reverse ranges.
Let me know what you think about it.

else State.Empty

// significantly simpler than the iterator returned by Iterator.unfold
override def unfold[A, S](init: S)(f: S => Option[(A, S)]): LazyList[A] =
newLL {
Expand Down
14 changes: 13 additions & 1 deletion test/junit/scala/collection/immutable/LazyListTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,20 @@ class LazyListTest {
LazyList(1).lazyAppendedAll({ count += 1; Seq(2)}).toList
assertEquals(1, count)
}

@Test
def lazyRangeAllowsMoreThanIntMaxValue(): Unit = {
val totalElements: Long = Int.MaxValue.toLong + 2L
val count: Long =
LazyList
.range(start = 0L, end = totalElements)
.foldLeft(0L) { case (acc, _) =>
acc + 1L
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even with inlining turned on, it's a lot to ask of a unit test. Maybe it's sufficient to test construction and head.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was wondering the same.
However, not sure if just asking for the head ensures there are more than Int.MaxValue elements.

So not sure if there is a smart way to test this without it being a CPU trap.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a reverse range we don't need to compute a lot of elements.
Let me know what you think of the new test.
C.C. @NthPortal

assertEquals(totalElements, count)
}
}

object LazyListTest {
var serializationForceCount = 0
}
}