I am currently dealing with some calculations that involve different collections of numbers, such as Vec<u16>
, Vec<u32>
, VecDeque<16>
, etc. I need to calculate the average of these collections several times, therefore I would like to wrap this:
let avg = numbers.map(|x| *x as u32).sum::<u32>() as f32 / numbers.len() as f32;
Into a function, where numbers
may be any collection.
I tried this:
fn average<T>(numbers: &T) -> f32 {
numbers.map(|x| *x as u32).sum::<u32>() as f32 / numbers.len() as f32
}
But that of course does not work because T
does not necessary implement Iterator
. So I added (MVCE):
use std::collections::VecDeque;
fn average<T>(numbers: &T) -> f32
where
T: std::iter::Iterator,
u32: std::iter::Sum<<T as std::iter::Iterator>::Item>,
u16: std::iter::Sum<<T as std::iter::Iterator>::Item>,
{
numbers.sum::<u32>() as f32 / numbers.count() as f32
}
fn main() {
let mut input = VecDeque::new();
input.push_back(1);
input.push_back(2);
let _avg = average(&input.iter());
}
But I get "the trait std::iter::Sum<&u32>
is not implemented for u16
", and I think this would not work anyway since count()
would consume the Iterator
.
So I decided to just make multiple functions over slices. e.g.:
fn average_u16<T>(numbers: &[u16]) -> f32 {
numbers.map(|x| *x as u32).sum::<u32>() as f32 / numbers.len() as f32
}
But that is not satisfying either, since a &VecDeque
is not a slice.
Can this be achieved somehow without depending on additional crates?