#rustlang folks up for a question?

I tried to convert a .fold() into a .reduce(), but it didn't work and I don't understand why. Math on shared references to ints seems to work in .fold, but not in .reduce?

fn main() {
let v = vec![1, 2, 3, 4];

// works
println!("{:?}", v.iter().fold(0, |acc, e| e + acc));
// fails: expected `&{integer}`, found integer
println!("{:?}", v.iter().reduce(|acc, e| e + acc).unwrap());
// changing to .into_iter() works
}

#rust

@briandorsey I'll give this a shot:

fold has a different output generic B in FnMut(B, Self::Item) -> B than the Self::Item, whereas reduce is FnMut(Self::Item, Self::Item) -> Self::Item. Both of these iterators are over &{integer}, but because you supply an integer as B, the compiler can infer that you want to return an integer. So it sees &integer + integer -> integer and knows to autodereference e. With reduce, it's trying to do &integer + &integer -> &integer and can't get there

@briandorsey …and using into_iter works because the Self::Item is integer not &integer
@jbr Thank you! This explanation helps me understand what I was missing, when reading the definitions in the docs.

@briandorsey compare type signature of the function argument. Fold can return anything, reduce must return value of a type iterator produces. into_iter gives you owned values which work, usual iter - references. You can add them but you can't return the addition result.

If you are dealing with addition - there's sum. copied might be also of interest.

@briandorsey reduce uses references because v.iter() is an iterator of references. And because the output type has to match the acc and e parameters, you need somewhere to store it.

However, if you use v.into_iter(), this produces an iterator that makes non-references and so you're returning a non-reference.