Reputation: 2609
In many languages (Fortran, Matlab/Octave, Julia, etc) an expression like sum(array,n)
will sum the values of an array along the n:th dimension and outputting an array of one lower dimensionality. Is there something equivalent in Rust?
I tried:
fn main() {
let arr1: [f64; 5] = [1.1, 1.2, 2.3, 3.4, 4.5555];
println!("this {}", arr1.iter().sum())
}
with this error:
error[E0282]: unable to infer enough type information about `_`
--> src/main.rs:3:37
|
3 | println!("this {}", arr1.iter().sum())
| ^^^ cannot infer type for `_`
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:3:5: 3:43 note: in this expansion of println! (defined in <std macros>)
|
= note: type annotations or generic parameter binding required
Upvotes: 0
Views: 647
Reputation: 29983
The "unable to infer enough type information about _
" error message is explained in a few other questions. See Error: unable to infer enough type information about `_`; type annotations or generic parameter binding required and Unable to infer enough type information about _; type annotations or generic parameter binding required. Basically, it means that the compiler doesn't have enough information to specify all type parameters in a function or a data type.
Nevertheless, this particular case may arouse some confusion: why can't Iterator.sum()
just infer the resulting sum's type to the iterator's Item
? By supposedly adding up f64
s, we'd be expecting f64
as an outcome, right? Well, the method sum
is actually defined like this:
fn sum<S>(self) -> S
where S: Sum<Self::Item>
Where S
implements another kind of sum
function (see trait Sum
) that takes an iterator:
pub trait Sum<A = Self> {
fn sum<I>(iter: I) -> Self where I: Iterator<Item=A>;
}
This trait gives us the freedom to sum numbers and references to numbers alike:
static MAGIC_CODE: u32 = 0xDEADBEEF;
static BLAND_CODE: u32 = 0x1234ABCD;
fn main() {
let sum1: u32 = vec![MAGIC_CODE, BLAND_CODE] // vec! infers to Vec<u32>
.into_iter().sum();
let sum2 = vec![&MAGIC_CODE, &BLAND_CODE] // vec! infers to Vec<&u32>
.into_iter().sum::<u32>();
assert_eq!(sum1, sum2);
}
On the other hand, this also means that the definition of a sum becomes more loose: any other data type implementing Sum<u32>
(or Sum<&u32>
) could take its place in the code above, which leads to the aforementioned ambiguity. For the purpose of demonstration, this code also compiles:
use std::iter::Sum;
struct Accumulator(bool);
impl Sum<u32> for Accumulator {
fn sum<I: Iterator<Item = u32>>(mut iter: I) -> Self {
Accumulator(iter.any(|v| v != 0))
}
}
fn main() {
let sum3: Accumulator = {
let data = vec![MAGIC_CODE, BLAND_CODE];
data.into_iter().sum()
};
assert!(sum3.0);
}
Upvotes: 1
Reputation: 15204
In this case you have to explicitly specify type of the elements:
println!("this {}", arr1.iter().sum::<f64>())
You were very close :)
Another option that were suggested by @E_net4 is to use separate binding:
let res: f64 = arr1.iter().sum();
println!("this {}", res)
Upvotes: 3