现在,如果不推荐使用num :: Zero和One,应该如何提供一个或零?

时间:2017-04-29 20:57:13

标签: generics types numbers rust

在编写我自己的通用sigma求和函数以使用Rust进行练习时,我遇到了一个问题,即将种子值设为零作为累加器。

fn sigma<I, T, F>(iter: I, func: F) -> T
    where I: Iterator<Item=T>,
          T: Add<Output=T>,
          F: Fn(T) -> T
{
    iter.fold(0, |acc, x| acc + func(x))
}

Playground Link

我明白这是错误的,因为0是具体类型,因此不是T。其他答案(例如thisthis one)依赖于Int::zero等结构,从1.11起为deprecated

还有其他方法可以做到这一点,但我特别感兴趣应该如何完成,因为测试一个,零或否定性是数字程序中的常见操作,我会再打一次就好了。另外,现在我很好奇。

我的Rust版本是1.16。

1 个答案:

答案 0 :(得分:4)

询问 然而,如果我们缩小到这两种方法,我认为这是典型和惯用的,这是可以回答的:

ZeroOne从标准库中被弃用(实际上从未稳定!),主要是因为有一种更通用的方法可以从迭代器中生成产品和总和:{{3}调用方法SumProduct时,迭代器依赖于sum()个特征,甚至可以产生除项目之外的类型的结果。

use std::iter::{Iterator, Sum};

fn sigma<I, T, F>(iter: I, func: F) -> T
    where I: Iterator<Item = T>,
          T: Sum,
          F: Fn(T) -> T
{

    iter.map(func).sum::<T>()
}

product()。我冒昧地将元素转换移动到迭代器定义链中的map,从而允许使用sum()作为终端操作。

特质PlaygroundZero仍然可以在包num(或num-traits)中使用,因此您可以使用它。

extern crate num;

use std::ops::Add;
use std::iter::Iterator;
use num::Zero;

fn sigma<I, T, F>(iter: I, func: F) -> T
    where I: Iterator<Item = T>,
          T: Zero + Add<Output = T>,
          F: Fn(T) -> T
{
    iter.map(func).fold(T::zero(), |a, b| a + b)
}

One