I have the following following sum
function for vectors of i32
that compiles and works fine:
fn sum_vec(s: &Vec<i64>, init: &i64) -> i64 {
(*s).iter().fold(*init, |acc, &item| acc + item)
}
To teach myself about Rust generics, I would like to define the corresponding generic function, for any type T
that implements addition of the form add(T, T) -> T
. I tried
use std::ops::Add;
fn sum_gen_1<T: Add>(s: &Vec<T>, init: &T) -> T {
(*s).iter().fold(*init, |acc, &item| acc + item)
}
But I get the following error
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`
It seems that one has to further constrain the implementation of the
Add
trait so that the type Add::Output
equals T
. Following some documentation found on the interwebz (probably for an old version of Rust), I tried changing the type constraint as to T: Add<T, T>
, i.e. declare the generic function as:
fn sum_gen_1<T: Add<T, T>>(s: &Vec<T>, init: &T) -> T
with the same function body as before. This time I got the error
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
What is the proper way to accomplish this? Should I use a different trait instead of Add
? Maybe define my own trait and implement it for the types I want my sum
to work for?
I noticed that the is a trait std::iter::AdditiveIterator
which would seem to make my implementation unnecessary. However, it is marked as unstable and any attempt to use it would cause a compile error when using rustc-1.0.0-beta.
You almost got it. Associated types must be given by name/keyword, so you're looking for
Add<T, Output = T>
.With that change, you face the problem that you liberally copy numbers around, but there is no
Copy
bound. I'd suggest the following implementation:Changing
&Vec<T>
to&[T]
has no effect, but it makes the function more general and loses nothing.See also:
After seeing the answer for vectors, I went on to implement essentially the same function for a general iterator of
T
:It seems a bit verbose to have to type
I::Item
or<I as Iterator>::Item
in three places... I've asked about that in Simplify where clause with repeated associated type restrictions