0

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Philipp Ludwig
  • 3,758
  • 3
  • 30
  • 48
  • 2
    See [num_traits](https://rust-num.github.io/num/num_traits/index.html) – Boiethios Feb 27 '19 at 10:39
  • See my question - I would like to avoid an additional crate. – Philipp Ludwig Feb 27 '19 at 10:45
  • 6
    Any strong reason why not using an external crate like `num_traits`? – hellow Feb 27 '19 at 10:45
  • [Example quick and dirty](https://play.integer32.com/?version=stable&mode=debug&edition=2018&gist=f731c553faaec53b4e444492d3bf8130) – Stargateur Feb 27 '19 at 11:21
  • 3
    @PhilippLudwig then go to num_traits and copy paste everything in it into your code. “Problem” “solved” – Shepmaster Feb 27 '19 at 12:33
  • 1
    [The duplicates applied to your problem](https://play.integer32.com/?version=stable&mode=debug&edition=2018&gist=512f174a297a115dad420e22a1656c29) – Shepmaster Feb 27 '19 at 13:18
  • @Shepmaster I don't see how any of those apply - there first two are using an external crate, what I wan't to avoid. In the third one I really don't understand what's going on, and even though I am thankful for your effort, that code you linked doesn't help me either - I came to SO to understand how this is done in Rust, so I can solve similar problems in the future by myself, not to copy+paste some code without understanding what's going on. – Philipp Ludwig Mar 01 '19 at 09:08
  • 1
    @PhilippLudwig While your points sound valid, this question still is a duplicate. If you are unsatisfied with the existing answers in the linked duplicate questions, you can post a bounty to one (or all) of those questions with the explicit reason that you wish for a more detailed canonical answer. – Max Vollmer Apr 08 '19 at 20:35

0 Answers0