This Rust tutoriel 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 pouvait être une erreur liée à la référence pour une raison quelconque, j'ai donc changé cela en fold(0, |sum, &val| sum += val)
, ce qui a entraîné
error: mismatched types:
expected `u32`,
found `()`
Hm, peut-être que quelque chose ne va pas avec la fermeture? En utilisant {sum += x; sum }
, J'ai obtenu
binary assignment operation `+=` cannot be applied to types `_` and `&u32`
encore.
Après d'autres essais et erreurs, l'ajout de mut
à sum
a fonctionné:
let sum = vec![1,2,3,4,5,6].iter().fold(0, |mut sum, &x| {sum += x; sum});
Quelqu'un pourrait-il expliquer la raison pour laquelle fold()
pour les vecteurs diffère tellement du tutoriel? Ou existe-t-il une meilleure façon de gérer cela?
Pour référence, j'utilise Rust beta, 2015-04-02.
Vous avez déjà compris que +=
Est le problème, mais j'aimerais fournir plus d'informations.
Dans votre cas, les arguments fournis pour la fermeture de fold
sont _
Et &u32
. Le premier type est un entier non encore spécifié. Si vous changez votre appel de repli en 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é. Cela explique le message d'erreur lorsque vous êtes passé à fold(0, |sum, &val| sum += val)
:
let mut a = 1;
let what_am_i = a += 1;
println!("{:?}", what_am_i); // => ()
Si vous passez à 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 sum
comme mutable, mais la bonne solution est de simplement plier avec sum + val
, Comme vous avez découvert.
Dans les versions plus récentes de Rust, vous pouvez également simplement sum
l'itérateur directement, en sautant fold
:
let sum: u32 = vec![1,2,3,4,5,6].iter().sum();
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 vous aidera, au cas où quelqu'un se retrouverait dans une situation similaire.