在编写我自己的通用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))
}
我明白这是错误的,因为0是具体类型,因此不是T
。其他答案(例如this和this one)依赖于Int::zero
等结构,从1.11起为deprecated。
还有其他方法可以做到这一点,但我特别感兴趣应该如何完成,因为测试一个,零或否定性是数字程序中的常见操作,我会再打一次就好了。另外,现在我很好奇。
我的Rust版本是1.16。
答案 0 :(得分:4)
询问 然而,如果我们缩小到这两种方法,我认为这是典型和惯用的,这是可以回答的:
Zero
和One
从标准库中被弃用(实际上从未稳定!),主要是因为有一种更通用的方法可以从迭代器中生成产品和总和:{{3}调用方法Sum
和Product
时,迭代器依赖于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()
作为终端操作。
特质Playground和Zero
仍然可以在包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)
}