The compiler errors provide a reasonable guide for fixing this code. If we ignore everything except the first error each time, the process looks like this:
error[E0308]: mismatched types
--> src/main.rs:8:18
|
4 | fn average<T>(numbers: &[T]) -> f32
| - this type parameter
...
8 | let sum: T = numbers.iter().sum() as f32;
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `f32`
| |
| expected due to this
|
= note: expected type parameter `T`
found type `f32`
You're trying to store an f32
into a variable of type T
. Make the variable f32
instead:
let sum: f32 = numbers.iter().sum() as f32;
error[E0282]: type annotations needed
--> src/main.rs:8:35
|
8 | let sum: f32 = numbers.iter().sum() as f32;
| ^^^ cannot infer type for type parameter `S` declared on the associated function `sum`
|
= note: type must be known at this point
help: consider specifying the type argument in the method call
|
8 | let sum: f32 = numbers.iter().sum::<S>() as f32;
| ^^^^^
Ok; we're summing T
's, so let's specify that the way the compiler hint suggests:
let sum: f32 = numbers.iter().sum::<T>() as f32;
error[E0277]: the trait bound `T: Sum<&T>` is not satisfied
--> src/main.rs:8:35
|
8 | let sum: f32 = numbers.iter().sum::<T>() as f32;
| ^^^ the trait `Sum<&T>` is not implemented for `T`
|
help: consider further restricting this bound
|
6 | T: num::PrimInt + Sum + Sum<&T>,
| ^^^^^^^^^
The iterator is providing &T
s instead of T
s. Primitive integers are Copy
, so we can use the copied
method to get past the reference:
let sum: f32 = numbers.iter().copied().sum::<T>() as f32;
error[E0605]: non-primitive cast: `T` as `f32`
--> src/main.rs:8:20
|
8 | let sum: f32 = numbers.iter().copied().sum::<T>() as f32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
We can't use an as
cast to convert between the generic type T
and the concrete one f32
, so we need another way to do this conversion. Fortunately, there's PrimInt::to_f32
:
let sum: f32 = numbers.iter().copied().sum::<T>().to_f32();
error[E0308]: mismatched types
--> src/main.rs:8:20
|
8 | let sum: f32 = numbers.iter().copied().sum::<T>().to_f32();
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f32`, found enum `Option`
| |
| expected due to this
|
= note: expected type `f32`
found enum `Option<f32>`
It apparently returns an Option
. In the absence of anything sensible to do with the conversion failure, we can just unwrap
it:
let sum: f32 = numbers.iter().copied().sum::<T>().to_f32().unwrap();
average = 86.7
Looks like we're done at this point. The process isn't particularly hard, but you do sometimes need to go several rounds with the compiler before reaching code that works.
(Playground)