-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add size_hints for btree iterators #49550
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1480,6 +1480,16 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { | |
unsafe { Some(self.next_unchecked()) } | ||
} | ||
} | ||
|
||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
if self.front == self.back { | ||
(0, Some(0)) | ||
} else { | ||
// There doesn't seem to be any way to get the size of the whole tree | ||
// from a NodeRef. | ||
(1, None) | ||
} | ||
} | ||
} | ||
|
||
#[stable(feature = "map_values_mut", since = "1.10.0")] | ||
|
@@ -1612,6 +1622,16 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { | |
unsafe { Some(self.next_unchecked()) } | ||
} | ||
} | ||
|
||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
if self.front == self.back { | ||
(0, Some(0)) | ||
} else { | ||
// We can get the root node by using into_root_mut; but there doesn't | ||
// seem to be any way to get the size of the tree from the root node. | ||
(1, None) | ||
} | ||
} | ||
} | ||
|
||
impl<'a, K, V> RangeMut<'a, K, V> { | ||
|
@@ -2549,4 +2569,19 @@ impl<K: Ord, V, I: Iterator<Item = (K, V)>> Iterator for MergeIter<K, V, I> { | |
} | ||
} | ||
} | ||
|
||
// Currently unused. However, BTreeMap::from_sorted_iter may some day be | ||
// rewritten to pre-allocate the correct amount of nodes, in which case | ||
// having this will be helpful. | ||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
let (left_lower, left_upper) = self.left.size_hint(); | ||
let (right_lower, right_upper) = self.right.size_hint(); | ||
let lower = left_lower + right_lower; | ||
let upper = match (left_upper, right_upper) { | ||
(Some(left), Some(right)) => left.checked_add(right), | ||
(left, None) => left, | ||
(None, right) => right | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Also, this lift can often be written nicely with ?-on-Option, something like (||{ left_upper?.checked_add(right_upper?) })() There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you are right! I got it backwards. I don't think it's worth it to create a closure purely to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, it'll soon be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's still a lot of |
||
}; | ||
(lower, upper) | ||
} | ||
} |
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.
What is the utility of a size hint like this? Would it be better to just not define it at all?
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 useful to have it, because it may be implemented in the future.
size_hint
is easily forgotten unless it's in the code.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'm not sure I buy that form of reasoning.
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.
In this particular case I buy it because
(1, None)
in some cases is still more information than the defaultsize_hint
of(0, None)
.But #49552 contains some
size_hint
implementations that literally just return(0, None)
. For those cases I don't think I buy it.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.
Well in particular, the bit about "because it may be implemented in the future." I'd rather not add speculative impls?
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.
@BurntSushi would just adding
// FIXME(#49205): Add size_hint
be better? I just want to make sure it's not forgotten.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.
@Ixrec I don't know what you're talking about? None of the implementations I wrote return
(0, None)
, or even this controversial(_, None)
... Please comment on that PR if you see any specific issues, maybe you see something I don't.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.
The other option is to add a
length
field like every other BTree iterator. But that isn't a trivial thing, which is what this PR is for.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'm just going to move forward with a FIXME. There's no consensus about what to do.