web-dev-qa-db-ja.com

フォールドを使用してベクトルを合計するにはどうすればよいですか?

これ 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`
_

再び。

さらに試行錯誤の後、mutsumに追加するとうまくいきました。

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

ベクトルのfold()がチュートリアルと大きく異なる理由を誰かが説明できますか?または、これを処理するより良い方法はありますか?

参考として、Rust beta、2015-04-02。

28
mmatyas

_+=_が問題であることはすでにわかっていますが、もう少し詳しく説明したいと思います。

あなたの場合、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`
_

ここから、couldcould(-===-)としてsumを変更可能としてマークしますが、正しい解決策は_sum + val_で単純にフォールドすることです発見されました。


Rustの新しいバージョンでは、 sum イテレータを直接使用して、foldをスキップすることもできます。

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

私が書いたように、私のコードには大きな違いがあることがわかりました

sum += x

の代わりに

sum + x

少なくとも、誰かが同様の状況に陥った場合に、この質問が役立つことを願っています。

9
mmatyas