and then sum()
knows to return an i32
To tutaj popełniłeś błąd. Sprawdź Iterator::sum
:
fn sum<S>(self) -> S
where S: Sum<Self::Item>
Zwraca ogólny typ S
który musi realizować Sum
. S
nie musi musi pasować do Self::Item
. Dlatego kompilator wymaga określenia typu, do którego należy dodać sumę.
Dlaczego ta funkcja jest przydatna? Sprawdź te dwie przykładowe implementacje ze standardowej biblioteki:
impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
Zgadza się! Można podsumować iterator z u8
lub iteratora z &u8
! Jeśli nie mamy tego, czym ten kod nie zadziała:
fn main() {
let a: i32 = (0..5).sum();
let b: i32 = [0, 1, 2, 3, 4].iter().sum();
assert_eq!(a, b);
}
As bluss points out, możemy to osiągnąć przez mającą skojarzony typ które mogłyby związać u8 -> u8
i &'a u8 -> u8
.
Gdybyśmy mieli tylko typ powiązany, to docelowy typ sumy byłby zawsze stały, a stracilibyśmy elastyczność. Na przykład możemy również wdrożyć Sum
dla naszych własnych typów.
W tym miejscu podsumowujemy u8
s, ale zwiększamy rozmiar typu, który sumujemy, ponieważ prawdopodobnie suma przekroczyłaby u8
. Ta realizacja jest w Ponadto do istniejących wdrożeń z biblioteki standardowej:
#[derive(Debug, Copy, Clone)]
struct Points(i32);
impl std::iter::Sum<u8> for Points {
fn sum<I>(iter: I) -> Points
where I: Iterator<Item = u8>
{
let mut pts = Points(0);
for v in iter {
pts.0 += v as i32;
}
pts
}
}
fn main() {
let total: Points = (0u8..42u8).sum();
println!("{:?}", total);
}
Powiązane pytanie: http: // stackoverflow.com/q/40243061/1233251 –