2015-04-09 12 views
19

This Rust poradnik wyjaśnia mechanizm fold() dobrze, a ten przykładowy kod:Jak podsumować wektor za pomocą złożenia?

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

działa zgodnie z oczekiwaniami.

Chciałbym uruchomić go na wektorze, więc na podstawie tego przykładu, pierwszy to pisałem:

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

który throwed błąd:

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

Domyśliłem się, że to może być błąd związany odniesienia dla jakiegoś powodu, więc zmieniłem że do fold(0, |sum, &val| sum += val), co wynikało z

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

Hm, może coś jest nie tak z zamknięciem? Korzystając ponownie z {sum += x; sum }, otrzymuję ponownie .

Po dalszych prób i błędów, dodając mut do sum pracował:

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

Może ktoś wyjaśnić, dlaczego fold() dla wektorów różni się tak bardzo od samouczka? Czy istnieje lepszy sposób na radzenie sobie z tym?

Dla porównania używam Rust beta, 2015-04-02.

+7

Ty wprowadziła dużą różnicę zastępując 'suma + x' przez' sum + = x' . – Levans

+0

Nie mogę w to uwierzyć, jak mógłbym tego przegapić ... Dzięki! – mmatyas

Odpowiedz

24

Już wiesz, że problemem jest +=, ale chciałabym podać trochę więcej ekspozycji.

W twoim przypadku argumenty dostarczone do zamknięcia fold to _ i &u32. Pierwszy typ to nie jest jeszcze określona liczba całkowita. Jeśli zmienisz połączenia krotny do fold(0u32, |sum, val| sum += val), dostaniesz nieco inną wiadomość:

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

Wartość wynikiem binarnym operacji przypisania += jest (), rodzaj jednostki.To wyjaśnia komunikat o błędzie, gdy zmienia się fold(0, |sum, &val| sum += val):

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

Jeśli zmieni się fold(0, |sum, &val| {sum += val ; sum}), następnie dostać zrozumiały błąd o zmiennych niezmiennych:

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` 

stąd, ty mógł oznaczyć sum jako zmienną, ale właściwym rozwiązaniem jest po prostu spasować z , jak odkryłeś.


W nowszych wersjach Rust, można też po prostu sum iterator bezpośrednio, omijając fold:

let sum: u32 = vec![1,2,3,4,5,6].iter().sum(); 
7

więc okazało się, to była ogromna różnica w kodzie, jak napisałem

sum += x

zamiast

sum + x.

Cóż, przynajmniej mam nadzieję, że to pytanie pomoże, na wypadek, gdyby ktoś znalazł się w podobnej sytuacji.

Powiązane problemy