Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LazyList.range [ci: last-only] #10767

Open
wants to merge 8 commits into
base: 2.13.x
Choose a base branch
from

Conversation

BalmungSan
Copy link
Contributor

Since LazyList is not strict, there is not reason to make range delegate through from(NumericRange) which doesn't allow more than Int.MaxValue elements.

@scala-jenkins scala-jenkins added this to the 2.13.15 milestone Apr 30, 2024
@SethTisue SethTisue requested a review from a team April 30, 2024 00:28
@SethTisue SethTisue added the library:collections PRs involving changes to the standard collection library label Apr 30, 2024
.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

@som-snytt som-snytt changed the title Fix LazyList.range Fix LazyList.range [ci: last-only] Apr 30, 2024
@som-snytt
Copy link
Contributor

added the magic title to avoid testing every commit

src/library/scala/collection/immutable/LazyList.scala Outdated Show resolved Hide resolved
.range(start = 0L, end = totalElements)
.foldLeft(0L) { case (acc, _) =>
acc + 1L
}
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.

BalmungSan and others added 2 commits April 30, 2024 11:32
Co-authored-by: Marissa | April <7505383+NthPortal@users.noreply.github.com>
Copy link
Contributor

@NthPortal NthPortal left a comment

Choose a reason for hiding this comment

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

just two small changes; otherwise lgtm.

I agree with @som-snytt's concern about the cost of iterating over Int.MaxValue elements, though I'm not really sure what the alternative is. I will defer to others' judgement about whether or not to just skip it

src/library/scala/collection/immutable/LazyList.scala Outdated Show resolved Hide resolved
src/library/scala/collection/immutable/LazyList.scala Outdated Show resolved Hide resolved
BalmungSan and others added 2 commits April 30, 2024 14:44
…tion

Co-authored-by: Marissa | April <7505383+NthPortal@users.noreply.github.com>
Co-authored-by: Marissa | April <7505383+NthPortal@users.noreply.github.com>
}

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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
library:collections PRs involving changes to the standard collection library
Projects
None yet
5 participants