-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add with_exact_size
and with_size_hint
to Iterator
#68995
Comments
Should |
I recall suggesting this to @scottmcm, who was not a fan, in a private setting at one point. |
I initially would have said: no, they should not panic. But thinking about it again... maybe checking this might not actually incur any notable performance overhead and be useful. Lets consider the implementation for struct ExactSize<I> {
inner: I,
size: usize,
}
impl<I: Iterator> Iterator for ExactSize<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
None => None,
Some(x) => {
self.size -= 1;
Some(x)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.size, Some(self.size))
}
} This implementation does not contain those checks. Well, in debug mode, the integer underflow is checked. Which is good, as an underflow would usually result in "no you can't allocate a gazillion GB". This would be match self.inner.next() {
None => {
assert_eq!(self.size, 0);
None
}
Some(x) => {
self.size = self.size.checked_sub(1).unwrap();
Some(x)
}
} The Well, this is certainly something we should benchmark and test before stabilization. |
For maximal optimization you'd need some sort of |
So I've been more and more thinking that what's really needed is a different iterator API that's allowed to be wrong, but where being wrong just over- or under-allocates, rather than permitting incorrect behaviour. Then things like ResultShunt can say "you should allocate enough for everything", even though it might return fewer things if there's an (I also still like |
Usually iterator adaptors do a fine job at keeping information about the length of an iterator. But once you throw something like
filter
in your iterator chain, the lower bound is 0, meaning that collecting into a collection can't properly pre-allocate. Also, some iterator adaptors (likechain
) cannot implementedExactSizeIterator
although in many real world cases, the size is perfectly known.Currently, working around those limitations is often tedious and requires quite a bit of additional code. I think it would be a lot nicer to just add a
.with_exact_size(27)
somewhere into your chain. So I'd like to propose adding the following toIterator
:fn with_size_hint(self, lower: usize, upper: Option<usize>) -> SizeHint
SizeHint
would implementIterator::size_hint
with the given values, forwarding all other methods to the inner iterator (and implementing the same traits)fn with_exact_size(self, size: usize) -> ExactSize
ExactSize
would implementExactSizeIterator
with the given value and overrideIterator::size_hint
. All other methods are forwarded to the inner iterator (and implementing the same traits, plusExactSizeIterator
)I would have created this as a PR, but I'm short on time and wanted to hear some opinions first.
The text was updated successfully, but these errors were encountered: