如何以通用方式定义向量(或迭代器)的和?

问题描述 投票:4回答:2

我有以下sum函数的i32矢量编译和工作正常:

fn sum_vec(s: &Vec<i64>, init: &i64) -> i64 {
    (*s).iter().fold(*init, |acc, &item| acc + item)
}

为了教自己关于Rust泛型,我想为任何类型的T定义相应的泛型函数,它实现了add(T, T) -> T形式的添加。我试过了

use std::ops::Add;

fn sum_gen_1<T: Add>(s: &Vec<T>, init: &T) -> T {
    (*s).iter().fold(*init, |acc, &item| acc + item)
}

但是我收到以下错误

error[E0308]: mismatched types
 --> src/lib.rs:4:42
  |
4 |     (*s).iter().fold(*init, |acc, &item| acc + item)
  |                                          ^^^^^^^^^^ expected type parameter, found associated type
  |
  = note: expected type `T`
             found type `<T as std::ops::Add>::Output`

似乎必须进一步限制Add特性的实施,以便类型Add::Output等于T。根据interwebz上的一些文档(可能是旧版本的Rust),我尝试将类型约束更改为T: Add<T, T>,即将泛型函数声明为:

fn sum_gen_1<T: Add<T, T>>(s: &Vec<T>, init: &T) -> T

具有与以前相同的功能体。这次我收到了错误

error[E0107]: wrong number of type arguments: expected at most 1, found 2
 --> src/lib.rs:3:17
  |
3 | fn sum_gen_1<T: Add<T, T>>(s: &Vec<T>, init: &T) -> T {
  |                 ^^^^^^^^^ expected at most 1 type argument

完成此任务的正确方法是什么?我应该使用不同的特性而不是Add吗?也许定义我自己的特性并为我希望我的sum工作的类型实现它?

我注意到这是一个特性std::iter::AdditiveIterator似乎使我的实现不必要。但是,它被标记为不稳定,任何使用它的尝试都会在使用rustc-1.0.0-beta时导致编译错误。

generics sum rust
2个回答
6
投票

你几乎得到了它。关联类型必须通过名称/关键字给出,因此您正在寻找Add<T, Output = T>

随着这种变化,你面临的问题是你自由地复制数字,但没有Copy绑定。我建议以下实现:

fn sum_vec<T>(s: &[T], init: &T) -> T
where
    T: Copy + Add<T, Output = T>,
{
    s.iter().fold(*init, |acc, &item| acc + item)
}

&Vec<T>更改为&[T]没有任何效果,但它会使函数更加通用并且不会丢失任何内容。

也可以看看:


1
投票

在看到向量的答案之后,我继续为T的一般迭代器实现基本相同的函数:

use std::ops::Add;

fn sum_iter<I>(s: I, init: &I::Item) -> I::Item
where
    I: Iterator + Clone,
    <I as Iterator>::Item: Add<I::Item, Output = I::Item> + Copy,
{
    s.clone().fold(*init, |acc, item| acc + item)
}

在三个地方打字I::Item<I as Iterator>::Item似乎有点啰嗦......我在Simplify where clause with repeated associated type restrictions问过这个问题

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.