使用fold如何对向量求和?

67
这个 Rust 教程很好地解释了 `fold()` 机制,并提供了以下示例代码:这里
let sum = (1..4).fold(0, |sum, x| sum + x);

按预期工作。

我想在一个向量上运行它,因此基于这个例子,我首先写了这个:

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

出现了错误:

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

我猜这可能是一个与引用相关的错误,所以我将其更改为fold(0, |sum, &val| sum += val),结果为:
error: mismatched types:
expected `u32`,
   found `()`

嗯,闭包可能有问题?使用{sum += x; sum },我得到了

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

经过进一步的尝试和错误,将mut添加到sum中成功了:

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

有没有人能解释一下为什么 fold() 对向量的处理与教程有很大不同?或者有更好的处理方法吗?

参考资料,我正在使用 Rust beta 版本,日期为 2015-04-02。


13
你通过将 sum + x 替换为 sum += x 引入了一个很大的差异。 - Levans
2
我简直不敢相信,我怎么会错过那个...谢谢! - mmatyas
2个回答

67
自 Rust 1.11 版本开始,您可以直接对迭代器进行求和操作(sum),无需使用fold函数。
let sum: u32 = vec![1, 2, 3, 4, 5, 6].iter().sum();

您已经发现了问题出在 += 上,但我想提供更多的解释。

在您的情况下,提供给 fold 闭包的参数是 _&u32。第一种类型是一个未指定的整数。如果您将折叠调用更改为 fold(0u32, |sum, val| sum += val),您将获得略微不同的消息:

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}`
二进制赋值操作符 += 的结果值为 (),即单位类型。这解释了当你将代码更改为 fold(0, |sum, &val| sum += val) 时产生的错误消息。
let mut a = 1;
let what_am_i = a += 1;
println!("{:?}", what_am_i); // => ()

如果您更改为fold(0,|sum,&val| {sum += val; sum}),那么您将收到一个有关不可变变量的易于理解的错误:

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`

从这里开始,你可以将 sum 标记为可变的,但正确的解决方案是简单地使用sum + val进行折叠,正如你所发现的那样。


19

结果证明,我的代码存在很大的差异,因为我写成了:

sum += x

而不是

sum + x

好吧,至少我希望这个问题能有所帮助,以防有人遇到类似的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接