Any suggestion as to how to label the type of std::iter::Map. I know closures are unnamable types, but what if I use an ordinary function? Is there any way to give the time of a map on an iterator?
Functions also have unnameable types, but both functions and captureless closures can coerce to function pointer types, fn(T) -> U. For example:
fn foo() -> std::iter::Map<std::vec::IntoIter<i32>, fn(i32) -> bool> {
vec![1,2,3,4].into_iter().map(|x| x > 3)
}
Note that this can affect code generation, because (unless it gets optimized away) this involves dispatching through a function pointer, unlike the original zero-sized closure or function type. Leaving the type unnamed does not have this problem:
fn foo() -> impl Iterator<Item=bool> {
vec![1,2,3,4].into_iter().map(|x| x > 3)
}
Another approach is to create your own map iterator. This way you can hardcode the closure in the next method.
struct MyMap<I> {
inner: I,
}
impl<I: Iterator<Item = u32>> Iterator for MyMap<I> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
self.inner.next().map(|i| 2*i)
}
}
Besides being verbose, this unfortunately has the disadvantage that you have to manually add extra iterator features such as size_hint and impls such as DoubleEndedIterator, ExactSizeIterator and TrustedLen if you use the iterator in a context where these are important.
Importantly, you lose TrustedLen and this disables a whole bunch of optimizations (related to collect) that can't be brought back. (TrustedLen is private to std)
Is there any way around this? I can't see a solution other than writing my own version of Map, which has all the above problems, or perhaps using a dyn Iterator, which introduces it's own runtime cost.
You can use the impl Iterator syntax that @mbrubeck suggested
Alas, that won't work for implementing IntoIterator. I use it for my other iterators, but can't do it for that one. ![]()
Yes, that is unfortunate.
If you are willing to use nightly, you can use existential_types to get a zero cost solution.
TrustedLen is not private to std.
Also, as far as collect, the default implementation literally just just calls from_iter through the generic result type, which doesn't inherently involve TrustedLen at all.
It's not available in std without unstable at least..
As for collect, it uses specialization implementations to allow FromIterator::from_iter to detect TrustedLen in the generic impl. This is a nightly only feature, but the standard library is still allowed to use it in stable because it's special. See also here.
Huh, looks like I misremembered. Thanks for the correction.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.