-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add an Iterator::batch
transformer and explicit size hints for FromIterator
and Extend
#14271
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
This transformer allows you to batch up multiple items in a stream of values into one value.
Some(it.by_ref().take(3).collect::<Vec<uint>>()) | ||
}).take(3); | ||
|
||
assert!(it.next() == Some(vec!(0, 1, 2))); |
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.
assert_eq
?
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.
I couldn't get assert_eq!()
to work in libcore because I can't get it to find the Show impl for Vec. I feel like I should be able to import Show
, but for some reason that doesn't work,
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.
I think it's because Vec
comes from realstd
, which means it's implementing a different Show
than the one compiled in this libcore
.
cc me |
pub trait FromIterator<A> {
/// Build a container with elements from an external iterator.
///
/// `cap_hint` is a hint as to what the capacity of the collection should be.
/// It is usually, but not always, the lower size bound of the iterator.
fn from_iter<T: Iterator<A>>(iterator: T, cap_hint: uint) -> Self;
}
pub trait Iterator<A> {
// ...
fn collect<B: FromIterator<A>>(&mut self) -> B {
let (lower, _) = self.size_hint();
FromIterator::from_iter(self.by_ref(), lower)
}
} Similarly we don't need |
Aside from my previous comment, I'm generally in favor of this patch. I'm not thrilled about making the core method of As for the suggested alternative to this patch, which is to change |
@kballard: I'm fine merging use std::FromIterator;
...
let x: Vec<int> = FromIterator::from_iter(iter, 10); It does have some nice symmetry with a Either way, I found maybe 10-20 spots in the stdlib we could use this |
@erickt I'm largely just concerned about API bloat. |
I would be more in favor of adding an iterator adaptor which modifies the return value of [1, 2, 3, 4].iter().filter(|&i| i %2 == 0).size_hint() // => (0, Some(4))
[1, 2, 3, 4].iter().filter(|&i| i %2 == 0).optimistic().size_hint() // => (4, Some(4)) |
@alexcrichton The only way to make this work is to redefine A problem with doing this alternative hint is defining how it changes as the iterator is used up. The current This is why I'm in favor of providing a way to override the capacity in |
Closing due to inactivity, but feel free to reopen with a rebase! |
Don't trigger unresolved method/field diagnostics on types containing errors
This pull request is focused on adding a
Iterator::batch
transformer.batch
allows you to batch up multiple values from a stream into one value. For example, this can be used for transforming a stream of a monotonically increasing infinite iterator likecount(0, 1)
into a stream ofvec!(0, 1, 2)
,vec!(3, 4, 5)
, and etc. It can also be seen as a low level transformer primitive that could be used to implement a variety of iterator transformers, as you could use it to implementmap
,filter
,reduce
, and more.Along the way this also adds support for passing an explicit size hints to
.collect()
,.from_iter()
and.extend()
in the form of.collect_with_capacity()
,.from_iter_with_capacity()
and.extend_with_capacity()
. Iterator size hints and.collect()
calls are generally conservative in the size of collections they preallocate. For example, a filter call likelet xs: Vec<int> = range(1, 5).filter(|x| x != 3).collect()
would initially allocate a zero-sizedVec<T>
because the.filter()
gives a lower bound of0
, andcollect
always uses the lower bounds. There is no way for the user to inform.collect()
to preallocate space for 4 items. Similarly, there isn't a way to overallocate a collection with.collect()
. These new methods allow the user to have better control over the memory allocation while still using generic methods.I have to admit though, I'm not sure if it's better to create methods like
.collect_with_capacity()
, or if we should rename.size_hint()
to.size_bounds()
, provide a newIterator.size_hint()
that may be outside the bounds of the values, and a.sized_by()
transformer that lets a user to provide a different hint than the lower bounds.Finally, it also adds some
.reserve_additional
methods on some collections, and cleans up some dead code.