I want to have a function, that accepts &IntoIterator<Item=u32>, so I could pass to it both &Vec<u32> and iterators' adapter structs (like Map, Filter and any other, which I believe all implement IntoIterator)
So I have a function like
pub fn f<'a, T>(it_src: &'a T) -> u32
where &'a T: IntoIterator<Item = u32> {
let it = it_src.into_iter();
let result: u32;
// more more usage
result
}
And this is how I tried to use it (same signature, but different name)
pub fn f_with_feature()<'a, T>(it_src: &'a T) -> u32
where &'a T: IntoIterator<Item = u32> {
let adjusted_values = it_src.into_iter()
.map(|e| adjust(e));
f(&adjusted_values)
}
What I've got is an error
error[E0308]: mismatched types
--> src\main.rs:14:7
|
14 | f(&adjusted_values)
| ^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::iter::Map`
|
= note: expected type `&T`
found type `&std::iter::Map<<&T as std::iter::IntoIterator>::IntoIter, [closure@src\main.rs:13:14: 13:27]>`
How is it that Map doesn't match as T?
Also, I've come up with an idea, that passing iterators' adaptors with static dispatch isn't a good idea since each other closure used to generate a Map will create a new function specialization. Though I've seen that static dispatch approach for most of the times is idiomatic in Rust. How to manage this situation?
I think you want to have trait bounds on T (and not on &'a T). So I guess you actually want the following:
pub fn f<'a, T>(it_src: &'a T) -> u32
where T: IntoIterator<Item = u32> {
let it = it_src.into_iter();
let result: u32 = 1;
// more more usage
result
}
pub fn f_with_feature<'a, T>(it_src: &'a T) -> u32
where T: IntoIterator<Item = u32> {
let adjusted_values = it_src.into_iter()
.map(|e| adjust(e));
f(&adjusted_values)
}
Which brings us to the next problem: IntoIterator's into_iter consumes self, which means that you cannot call it_src.into_iter if you only borrow it_src.
So if you really want to use into_iter, you can try this:
pub fn f<T>(it_src: T) -> u32
where T: IntoIterator<Item = u32> {
let it = it_src.into_iter();
let result: u32 = 1;
// more more usage
result
}
pub fn f_with_feature<T>(it_src: T) -> u32
where T: IntoIterator<Item = u32> {
let adjusted_values = it_src.into_iter()
.map(|e| adjust(e));
f(adjusted_values)
}
The above, however, requires you to move the values into f resp. f_with_feature.
In my experience, just taking an iterator (and doing the conversion at call site if necessary), leads to simple, straightforward solutions:
pub fn f<T>(it_src: T) -> u32
where T: Iterator<Item = u32> {
let it = it_src.into_iter();
let result: u32 = 1;
// more more usage
result
}
pub fn f_with_feature<T>(it_src: T) -> u32
where T: Iterator<Item = u32> {
let adjusted_values = it_src.into_iter()
.map(|e| adjust(e));
f(adjusted_values)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With