Comment puis-je additionner un vecteur en utilisant fold?

Ce tutoriel Rust explique bien le mécanisme fold(), et cet exemple de code:

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

Fonctionne comme prévu.

Je voudrais l'exécuter sur un vecteur, donc sur la base de cet exemple, j'ai d'abord écrit ceci:

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

, Qui a jeté une erreur:

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

J'ai deviné que cela pourrait être une erreur liée à la référence pour une raison quelconque, donc j'ai changé cela en fold(0, |sum, &val| sum += val), ce qui a abouti à

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

Hm, peut-être que quelque chose ne va pas avec la fermeture? En Utilisant {sum += x; sum }, Je got

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

Encore.

Après d'autres essais et erreurs, ajouter mut à sum travaillé:

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

Quelqu'un pourrait-il expliquer pourquoi fold() pour les vecteurs diffère tellement du tutoriel? Ou est-il une meilleure façon de gérer cela?

Pour référence, j'utilise Rust beta, 2015-04-02.

21
demandé sur Matthias Braun 2015-04-09 23:55:45

2 réponses

Vous avez déjà compris que += est le problème, mais je voudrais fournir plus d'exposition.

, Dans votre cas, les arguments fournis à la fold fermeture sont _ et &u32. Le premier type est un entier non encore spécifié. Si vous changez votre appel fold à fold(0u32, |sum, val| sum += val), vous obtiendrez un message légèrement différent:

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}`

La valeur de résultat de l'opération d'affectation binaire += est (), le type d'unité. Ceci explique le message d'erreur lorsque vous avez changé pour fold(0, |sum, &val| sum += val):

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

Si vous changez pour fold(0, |sum, &val| {sum += val ; sum}), Vous obtenez alors une erreur compréhensible sur les variables immuables:

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`

À partir de là, vous pourriez marquer {[15] } comme mutable, mais la solution correcte est de simplement plier avec sum + val, comme vous l'avez découvert.


Dans les nouvelles versions de Rust, vous pouvez également sum l'itérateur directement, en sautant fold:

let sum: u32 = vec![1,2,3,4,5,6].iter().sum();
27
répondu Shepmaster 2016-10-13 12:04:02

Il s'est donc avéré qu'il y avait une énorme différence dans mon code, comme je l'ai écrit

sum += x

Au Lieu de

sum + x.

Eh bien, au moins j'espère que cette question Aide, au cas où quelqu'un se retrouverait dans une situation similaire.

7
répondu mmatyas 2015-04-09 21:10:52