How do I sum a vector using fold?

46,178

Solution 1

Since Rust 1.11, you can sum the iterator directly, skipping fold:

let sum: u32 = vec![1, 2, 3, 4, 5, 6].iter().sum();

You've already figured out that += is the problem, but I'd like to provide some more exposition.

In your case, the arguments provided to the fold closure are _ and &u32. The first type is an not-yet-specified integer. If you change your fold call to fold(0u32, |sum, val| sum += val), you'll get a slightly different message:

let sum: u32 = vec![1,2,3,4,5,6].iter().fold(0u32, |sum, val| sum += val);
error[E0308]: mismatched types
  |
2 |     let sum: u32 = vec![1,2,3,4,5,6].iter().fold(0u32, |sum, val| sum += val);
  |                                                                          ^^^ expected u32, found &{integer}
  |
  = note: expected type `u32`
  = note:    found type `&{integer}`

The result value of the binary assignment operation += is (), the unit type. This explains the error message when you changed to fold(0, |sum, &val| sum += val):

let mut a = 1;
let what_am_i = a += 1;
println!("{:?}", what_am_i); // => ()

If you change to fold(0, |sum, &val| {sum += val ; sum}), you then get an understandable error about immutable variables:

let sum: u32 = vec![1,2,3,4,5,6].iter().fold(0, |sum, &val| {sum += val; sum});
error[E0384]: re-assignment of immutable variable `sum`
 --> src/main.rs:2:66
  |
2 |     let sum: u32 = vec![1,2,3,4,5,6].iter().fold(0, |sum, &val| {sum += val; sum});
  |                                                      ---         ^^^^^^^^^^ re-assignment of immutable variable
  |                                                      |
  |                                                      first assignment to `sum`

From here, you could mark sum as mutable, but the correct solution is to simply fold with sum + val, as you discovered.

Solution 2

So it turned out there was a huge difference in my code, as I wrote

sum += x

instead of

sum + x

Well, at least I hope this question helps, in case someone gets into similar situation.

Share:
46,178
mmatyas
Author by

mmatyas

Updated on July 08, 2022

Comments

  • mmatyas
    mmatyas almost 2 years

    This Rust tutorial explains the fold() mechanism well, and this example code:

    let sum = (1..4).fold(0, |sum, x| sum + x);
    

    works as expected.

    I'd like to run it on a vector, so based on that example, first I wrote this:

    let sum: u32 = vec![1,2,3,4,5,6].iter().fold(0, |sum, val| sum += val);
    

    which threw an error:

    error: binary assignment operation `+=` cannot be applied to types `_` and `&u32` [E0368]
    let sum = ratings.values().fold(0, |sum, val| sum += val);
                                                  ^~~~~~~~~~
    

    I guessed this might be a reference-related error for some reason, so I changed that to fold(0, |sum, &val| sum += val), which resulted in

    error: mismatched types:
    expected `u32`,
       found `()`
    

    Hm, maybe something's wrong with the closure? Using {sum += x; sum }, I got

    binary assignment operation `+=` cannot be applied to types `_` and `&u32`
    

    again.

    After further trial and error, adding mut to sum worked:

    let sum = vec![1,2,3,4,5,6].iter().fold(0, |mut sum, &x| {sum += x; sum});
    

    Could someone explain the reason why fold() for vectors differs so much from the tutorial? Or is there a better way to handle this?

    For reference, I'm using Rust beta, 2015-04-02.