如何以通用方式定义向量(或迭代器)的总和?
How to define sum over vectors (or iterators) in a generic way?
对于 i32
的向量,我有以下 sum
函数可以编译并正常工作:
fn sum_vec(s: &Vec<i64>, init: &i64) -> i64 {
(*s).iter().fold(*init, |acc, &item| acc + item)
}
为了自学 Rust 泛型,我想为实现 add(T, 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 时导致编译错误。
你差不多明白了。关联类型必须由 name/keyword 给出,因此您正在寻找 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]
没有效果,但是让函数更通用,没有损失。
另请参阅:
看到向量的答案后,我继续为 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
中询问过这个问题
对于 i32
的向量,我有以下 sum
函数可以编译并正常工作:
fn sum_vec(s: &Vec<i64>, init: &i64) -> i64 {
(*s).iter().fold(*init, |acc, &item| acc + item)
}
为了自学 Rust 泛型,我想为实现 add(T, 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 时导致编译错误。
你差不多明白了。关联类型必须由 name/keyword 给出,因此您正在寻找 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]
没有效果,但是让函数更通用,没有损失。
另请参阅:
看到向量的答案后,我继续为 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