Return concrete types from LiteMap iter methods#8072
Conversation
|
|
Manishearth
left a comment
There was a problem hiding this comment.
This is a good idea. Generally we should do this more to make it easier to compose our iterators.
Waiting on CLA.
|
I'll keep up to date with the CLA application progression. I just submitted it to management. |
sffc
left a comment
There was a problem hiding this comment.
This looks about right. I don't like how Rust doesn't have a good way to automatically delegate the Iterator trait. You picked 4 fns here, which seem like good ones, but you could have picked more or fewer; there isn't a great way to pick which ones to leave as default.
| { | ||
| /// Produce an ordered iterator over key-value pairs | ||
| pub fn iter(&'a self) -> impl DoubleEndedIterator<Item = (&'a K, &'a V)> { | ||
| pub fn iter(&'a self) -> S::KeyValueIter { |
There was a problem hiding this comment.
Thought: This is fine since S::KeyValueIter is already public and already used in a bunch of bounds.
An alternative would be to add a third iterator wrapper for this.
|
I have the CLA documents signed, I need to scan them and send them to the unicode org email still. I will implement the suggested changes to the PR, and rebase. |
54fdeab to
0a00977
Compare
| impl_const_get_with_index_for_integer!(i128); | ||
| impl_const_get_with_index_for_integer!(isize); | ||
|
|
||
| type MapKv<'a, I, K, V, Out> = core::iter::Map<I, fn((&'a K, &'a V)) -> &'a Out>; |
There was a problem hiding this comment.
This is the biggest worry here for me, I'm not sure how the compiler handles the function pointer. In practice, it will always be the closure used in LiteMap::values and LiteMap::keys passed to iter().map(_), so I don't know if the compiler is smart enough to directly inline the closure.
The alternative is described in the PR description, which might make the exposed type quite difficult to read.
There was a problem hiding this comment.
It's probably fine. But, since you're exporting a new type anyway, a cleaner solution would be to remove the core::iter::Map and just do the mapping in the fns you are implementing. The map fn is only a field access.
pub struct KeysIter<'a, K, V, S: StoreIterable<'a, K, V>> {
iter: S::KeyValueIter
}
impl<'a, K, V, S: StoreIterable<'a, K, V>> Iterator for KeysIter<'a, K, V, S> {
type Item = &'a K;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// don't need to map here
self.iter.size_hint()
}
#[inline]
fn next(&mut self) -> Option<Self::Item> {
// access the .0 of the value using Option::map
self.iter.next().map(|val| &val.0)
}
#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
// here we can apply a map fn
self.iter.map(|val| val.0).fold(init, f)
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(|val| &val.0)
}
}There was a problem hiding this comment.
Good point, with this, it's also possible to make KeysIter and ValuesIter generic over the iterator itself rather than S: StoreIterable which allows to use derive for the Debug and Clone impls.
0a00977 to
5a66aa0
Compare
|
15fca4b to
e4d4097
Compare
|
Applying the suggestion from @sffc wrt to mapping inside the methods rather than before creating the iterator (I should have thought about that) made the code much cleaner, since Looking at the code for implementing CLA ETA: Email sent yesterday, waiting for the reply. |
impl Trait is limited to a single trait. But we'd like to expose iterators that implement more than DoubleEndedIterator (eg: ExactSize, Fused). This is why we return a concrete type now. This closes unicode-org#8054. Considerations -------------- * No Copy derive, because that's against API guidelines for Iterators * Manual impl of `size_hint`, to be able to use ExactSizeIterator without panicking. * Manual impl of `nth` and `fold`, as other iterator methods tend to be implemented in term of those, and forwarding them to the inner iterator **might** avoid performance penalty of the default impl.
e4d4097 to
4ed57de
Compare
Return concrete types from LiteMap iter methods
impl Trait is limited to a single trait. But we'd like to expose
iterators that implement more than DoubleEndedIterator (eg: ExactSize,
Fused). This is why we return a concrete type now.
This closes #8054.
Considerations
size_hint, to be able to use ExactSizeIteratorwithout panicking.
nthandfold, as other iterator methods tend to beimplemented in term of those, and forwarding them to the inner
iterator might avoid performance penalty of the default impl.
CLA status
CLA ETA: Got back an email confirmation from the Unicode member service 06/07/2026
Changelog
litemap: Make return types of
LiteMapiter methods (iter,iter_mut,values,keys) concrete:ValuesIter,KeysIter, implements relevant traits, returned byvaluesandkeysrespectively.impl DoubleEndedIteratorto concrete types such asS::KeyValueIter,S::KeyValueIterMutor the aforementioned new types.