Skip to content
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

imbl::ordmap::RangedIter does not implement ExactSizeIterator #97

Closed
optevo opened this issue Jan 26, 2025 · 3 comments
Closed

imbl::ordmap::RangedIter does not implement ExactSizeIterator #97

optevo opened this issue Jan 26, 2025 · 3 comments

Comments

@optevo
Copy link

optevo commented Jan 26, 2025

Impact:
While RangedIter implements DoubleEndedIterator, .rev() is not fully supported beyond the first call when combined with adaptors like take(). This is because take() requires the iterator to implement ExactSizeIterator, as subsequent calls to .rev() depend on knowing the iterator’s exact length via len() provided by ExactSizeIterator.

This is a breaking change introduced from version 3.0.0 to 4.0.0 as ExactSizeIterator was implemented on imbl::ordmap::Iter

@jneem
Copy link
Owner

jneem commented Jan 27, 2025

That's right: this was called out in the changelog here, and was the reason for bumping the major version number. More context at #85: your reliance on ExactSizeIterator was probably producing incorrect results.

@jneem jneem closed this as completed Jan 27, 2025
@optevo
Copy link
Author

optevo commented Jan 28, 2025

Thanks sorry missed it. Do you have a recommended efficient workaround to iterate in reverse - get_prev? What are the challenges around implementing a correct ExactSizeIterator? Iterator impl needs size_hint() to return correct size so initialise with len() then decrement as consumed which it could track in the struct no? I'm missing something?

@jneem
Copy link
Owner

jneem commented Jan 28, 2025

Iterating in reverse on its own is fine, because RangedIter implements DoubleEndedIterator. But if you want to do something like map.range(a..b).take(10).next_back(), I think the most efficient way is to collect map.range(a..b).take(10) into a Vec and then you can iterate over that vec as much as you like.

Implementing a correct ExactSizeIterator would require a lot of length-tracking internally and it would impose a cost on all other usages of OrdMap. The standard library BTreeMap doesn't support it either, probably for that reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants