用于平均函数的Rust泛型语法

blo*_*ley 1 generics math syntax rust

我正在尝试编写一个函数,它接受一些数字并计算平均值.

我尝试使用实现泛型函数的想法来获得泛型类型,但是会出错.

我的代码是:

extern crate num;

use num::{FromPrimitive, Zero};
use std::ops::{Add, Div};

fn main() {
    let mut numbers = [10, -21, 15, 20, 18, 14, 18];
    let err = "Slice is empty.";

    println!("Mean is {:.3}", mean(&numbers).expect(err));
}

fn mean<T>(numbers: &[T]) -> Option<f64>
where
    T: Copy + Zero + Add<T, Output = T> + Div<T, Output = T> + FromPrimitive,
{
    match numbers.len() {
        0 => None,
        _ => {
            let sum = numbers.iter().sum: ();
            let length = FromPrimitive::from_usize(numbers.len()).unwrap();
            Some(sum / length)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误是:

error[E0658]: type ascription is experimental (see issue #23416)
  --> src/main.rs:20:23
   |
20 |             let sum = numbers.iter().sum: ();
   |                       ^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

有没有办法在不使用实验性功能的情况下编写通用均值函数?

Öme*_*den 7

您的类型也需要实现Sum<T>,因此您还需要添加f64绑定.这还不够,您还需要将您的泛型类型转换为ToPrimitive.num crate也有Sum<T>这样做的特点:

fn mean<'a, T: 'a>(numbers: &'a [T]) -> Option<f64>
where
    T: ToPrimitive + Sum<&'a T>,
{
    match numbers.len() {
        0 => None,
        _ => {
            let sum = numbers.iter().sum::<T>();
            let length = f64::from_usize(numbers.len())?;

            T::to_f64(&sum).map(|sum| sum / length)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

操场

  • @blokeley *取一些数字的平均值* —这是“问题”:您不是取“某些数字”的平均值。您正在使用可以表示某些属性集的任何泛型类型的均值。在Python中,您可以将字符串集合传递给等效函数并获得运行时错误。等效的Rust代码会强制您在编译代码时所做的任何事情都是有效的。您可以创建自己的* own *特性,并将其仅用于数字,以降低此功能的表面复杂性。 (2认同)