-
Notifications
You must be signed in to change notification settings - Fork 321
Add fold_mut alternative to fold #481
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
Conversation
Based on the discussions on rust-lang/rust#76746
group.bench_function("fold", |b| { | ||
b.iter(|| { | ||
(0i64..1_000_000) | ||
.chain(0i64..1_000_000) |
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.
Added a benchmark with chain
to show that, because fold_mut
uses for_each
, it benefits from Chain
's specialization of fold
/// # Examples | ||
/// ``` | ||
/// # use itertools::Itertools; | ||
/// let evens = [1, 2, 3, 4, 5, 6].iter().fold_mut(Vec::new(), |evens, &num| { |
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.
Is this example too lame? I was going to use the example of counting but ... there's .counts
right above this so that seemed worse haha
This bugged me in some of my projects, too. However, I realized that I then needed e.g. Thus, I solved this in a different way: I introduced
In my implementation I assumed that the compiler is clever enough to optimize it as good as possible in any case - which, reading your PR, seems wrong. So, my questions:
|
Great question! I have no idea 🤔 I imagine it'd be great to have this variant of all the methods since you can implement
Maybe! There's a little discussion going on here. I do think that, if we could get |
Just checking back in for some quick guidance here - should I be working to implement |
I think this is sufficiently stale to close :-) |
This PR
Adds a
fold_mut
alternative tofold
Why?
fold
requires an awkward final line to return the accumulator as mentioned here.fold_mut
can be faster. And sometimes it can be slower! See the benchmarks here. TL;DR, if the accumulator is at least as big as a&mut
to the accumulator,fold
can be slower thanfold_mut
as moving the larger accumulator is more work than moving the&mut
.Background
A lot of the background is in this issue and this PR. Based on the discussion there, it seemed that this wasn't warranted for the standard library so I figured I'd pitch it here!
Benchmarks
I ran the benchmarks like:
(not sure if there's a shorter syntax) and saw:
i64
vec
chain
ed iterator into ani64
chain
ed iterator into avec
I could also add a benchmark with like an
i8
or something to show how much fasterfold
is when folding into something much smaller than a reference if we want that! I just had a hard time coming up with an accumulator that wouldn't overflow but would still be super readable. It might be like(0i8..10).chain(-10i8..0).cycle().take(1_000_000)
or some such.