-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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 length of Iterators.Stateful with underlying mutable iterator #45924
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think it might remain useful to keep the prior behavior also, by using the signbit instead of a Union. Commented my suggestions on how to do that.
base/iterators.jl
Outdated
rem = s.remaining | ||
if rem !== nothing | ||
s.remaining = rem - 1 | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rem = s.remaining | |
if rem !== nothing | |
s.remaining = rem - 1 | |
end | |
rem = s.remaining | |
@assert !iszero(rem) | |
s.remaining = rem - 1 |
I can make these changes, no problem. But I don't quite understand:
|
Mostly just to avoid any possible regression here. Though
Yeah, that was my hope |
Previously, Iterators.Stateful kept track of how many elements have been taken, and reported its length as the length of the underlying iterator minus the number of taken elements. However, this assumes the underlying iterator is immutable. If it is mutable, then the reported length is the same as the number of remaining elements, meaning the wrapper Stateful should not subtract the number of taken elements. After this PR, Stateful instead stores the length of the underlying iterator, if that can be known, and subtracts one every time an element is taken. Hence, the number of remaining elements is being kept track of directly. Fixes JuliaLang#43245
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
@vtjnash I think this should be good to go, and would be nice to get in v1.9 :) |
Thanks for the bump |
Bisected that this introduced a regression reported at #46719. |
PR JuliaLang#45924 fixed length of Stateful, but this change requires Stateful to call length on its wrapped iterator on instantiation. The current implementation of cmp(::AbstractString, ::AbstractString) wraps the strings in Stateful to efficiently check if one string is longer than the other without needing an O(N) call to length. However, with JuliaLang#45924 this length call is done anyway, which led to a performance regression. In this PR, the cmp method is changed so it no longer relies on Stateful to do the same thing. Fix JuliaLang#46719
PR #45924 fixed length of `Stateful`, but this change requires `Stateful` to call `length` on its wrapped iterator on instantiation. The current implementation of `cmp(::AbstractString, ::AbstractString)` wraps the strings in `Stateful` to efficiently check if one string is longer than the other without needing an O(N) call to `length`. However, with #45924 this length call is done anyway, which led to a performance regression. In this PR, the `cmp` method is changed so it no longer relies on `Stateful` to do the same thing. Fix #46719
Previously, Iterators.Stateful kept track of how many elements have been taken,
and reported its length as the length of the underlying iterator minus the
number of taken elements.
However, this assumes the underlying iterator is immutable. If it is mutable,
then the reported length is the same as the number of remaining elements,
meaning the wrapper Stateful should not subtract the number of taken elements.
After this PR, Stateful instead stores the length of the underlying iterator,
if that can be known, and subtracts one every time an element is taken. Hence,
the number of remaining elements is being kept track of directly.
Fixes #43245