均值函数的Rust泛型语法 [英] Rust generics syntax for mean function

查看:251
本文介绍了均值函数的Rust泛型语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个函数,该函数采用一片数字并计算均值.

I'm trying to write a function which takes a slice of numbers and calculates the mean.

我尝试使用>为通用类型实现均值函数的想法,但是出现错误.

I tried using the ideas from Implementing mean function for generic types but get an error.

我的代码是:

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)
        }
    }
}

错误是:

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

有没有不用实验特性就可以编写通用均值函数的方法吗?

Is there any way of writing a generic mean function without using experimental features?

推荐答案

这是怎么回事:

use std::iter::Sum;

fn main() {
    let err = "Slice is empty.";

    // Test vector of integers
    let numbers = vec![10i32, -21, 15, 20, 18, 14, 18];
    println!("Mean is {:.3}", mean(numbers.into_iter()).expect(err));

    // Test vector of floating point numbers
    let numbers = vec![10f64, -21f64, 15f64, 20f64, 18f64, 14f64, 18f64];
    println!("Mean is {:.3}", mean(numbers.into_iter()).expect(err));

    // Test empty vector
    let numbers: Vec<i32> = Vec::new();    
    println!("Mean is {:.3}", mean(numbers.into_iter()).expect(err));
}

fn mean<T, I: Iterator<Item = T>>(iter: I) -> Option<f64>
where
    T: Into<f64> + Sum<T>,
{
    let mut len = 0;
    let sum = iter
        .map(|t| {
            len += 1;
            t
        })
        .sum::<T>();

    match len {
        0 => None,
        _ => Some(sum.into() / len as f64)
    }
}

Rust Playground中的相同代码

与到目前为止发布的答案相比,它似乎具有以下优势:

It seems to have the following advantages over the answers posted so far:

  1. 更简单的泛型类型定义.
  2. 不依赖外部num条板箱.
  3. 不需要像FromPrimitiveZero这样难以猜测的特征.
  4. 没有手动的生命周期声明.
  1. Much simpler generic type definition.
  2. No reliance on external num crate.
  3. No need for difficult-to-guess traits like FromPrimitive and Zero.
  4. No manual lifetimes declarations.

此版本与上述版本有以下差异:

Or this version which has the following differences to the one above:

  1. 可以采用数组而不是向量.
  2. 不消耗数组(或向量).
  3. 需要手动的生命周期声明.

use std::iter::Sum;

fn main() {
    let err = "Slice is empty.";

    // Test aray of integers
    let numbers = [10, -21, 15, 20, 18, 14, 18];
    println!("Mean is {:.3}", mean(numbers.iter()).expect(err));

    // Test array of floating point numbers
    let numbers = [10f64, -21f64, 15f64, 20f64, 18f64, 14f64, 18f64];
    println!("Mean is {:.3}", mean(numbers.iter()).expect(err));

    // Test empty array
    let numbers: [i32; 0] = [];
    match mean(numbers.iter()) {
        Some(mean_) => println!("Mean is {:.3}", mean_),
        None => println!("Empty array"),
    }
}

fn mean<'a, T, I>(iter: I) -> Option<f64>
where
    T: Into<f64> + Sum<&'a T> + 'a,
    I: Iterator<Item = &'a T>,
{
    let mut len = 0;
    let sum = iter
        .map(|t| {
            len += 1;
            t
        })
        .sum::<T>();

    match len {
        0 => None,
        _ => Some(sum.into() / len as f64),
    }
}

感谢我的朋友Sven对代码的贡献.

Thanks to my friend Sven for code contribution.

这篇关于均值函数的Rust泛型语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆