首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >平均函数的锈蚀泛型语法

平均函数的锈蚀泛型语法
EN

Stack Overflow用户
提问于 2019-01-13 11:23:45
回答 4查看 1.4K关注 0票数 1

我试图编写一个函数,它接受一段数字并计算平均值。

我尝试使用泛型类型均值函数的实现的想法,但得到了一个错误。

我的代码是:

代码语言:javascript
复制
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)
        }
    }
}

错误是:

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

在不使用实验特性的情况下,是否有编写通用均值函数的方法?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-01-15 09:22:20

这个怎么样:

代码语言:javascript
复制
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)
    }
}

铁锈游乐场中的相同代码

与迄今公布的答案相比,它似乎具有以下优点:

  1. 更简单的泛型类型定义。
  2. 不依赖外部num箱。
  3. 不需要像FromPrimitiveZero这样难以猜测的特征。
  4. 没有手动生命周期声明。

或与上面的版本有以下区别的版本:

  1. 可以采用数组而不是向量。
  2. 不使用数组(或向量)。
  3. 需要手动的生存期声明。
代码语言:javascript
复制
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),
    }
}

感谢我的朋友斯文的代码贡献。

票数 1
EN

Stack Overflow用户

发布于 2019-01-13 12:39:25

在泛型函数中执行两种不同的操作:

  • 对片中的所有值进行求和:,您需要通过在泛型类型参数中添加Sum<T>边界来告诉元素是可加的。
  • 除法操作包含两个元素:,您的泛型类型需要转换为f64或任何要限制的浮点类型。由于您使用的是num机箱,所以我添加了ToPrimitive作为边界,这告诉您可以将泛型类型转换为基本类型。

以下是实现:

代码语言:javascript
复制
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)
        }
    }
}

游乐场

票数 7
EN

Stack Overflow用户

发布于 2019-01-13 13:49:33

其他答案可能会帮助您解决编写此函数的实际问题。

但是,您询问的实际错误只是语法错误。你写了这个:

代码语言:javascript
复制
let sum = numbers.iter().sum: ();

但几乎可以肯定地说:

代码语言:javascript
复制
let sum = numbers.iter().sum();

编译器看到了意外包含的:,并认为您正在尝试使用类型归属。类型归属是在表达式中使用类型注释的语法,而不是仅在变量声明中使用类型注释。

您所写的内容非常类似于:

代码语言:javascript
复制
let sum: () = numbers.iter().sum;

如果要在夜间的rustc构建中启用类型归属,则错误会发生变化,因为现在编译器将告诉您sum是一个函数,并且肯定没有()类型。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54168352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档