2016-12-07 107 views
6

此代碼的工作:Rust爲什麼不能推斷Iterator :: sum的結果類型?

fn main() { 
    let a: i32 = (1i32..10).sum(); 
    let b = a.pow(2); 
} 

如果我從a刪除i32類型,然後我得到這個錯誤:

rustc 1.13.0 (2c6933acc 2016-11-07) 
error: the type of this value must be known in this context 
--> <anon>:3:13 
    | 
5 |  let b = a.pow(2); 
    |    ^^^^^^^^ 

Run the example

我本來期望生鏽變成(1i32..10)i32迭代器,然後sum()知道要返回i32。我錯過了什麼?

+0

相關問題:http:// stackoverflow。com/q/40243061/1233251 –

回答

6

方式sum定義,它實際上是模糊的;不止一種類型可以實現Sum<i32>。下面是其中不同類型的用於a被使用,這兩種編譯一個例子:

#[derive(Clone,Copy)] 
struct Summer { 
    s: isize, 
} 

impl Summer { 
    fn pow(&self, p: isize) { 
     println!("pow({})", p); 
    } 
} 

impl std::iter::Sum<i32> for Summer { 
    fn sum<I>(iter: I) -> Self 
     where I: Iterator<Item = i32> 
    { 
     let mut result = 0isize; 
     for v in iter { 
      result += v as isize; 
     } 
     Summer { s: result } 
    } 
} 

fn main() { 
    let a1: i32 = (1i32..10).sum(); 
    let a2: Summer = (1i32..10).sum(); 
    let b1 = a1.pow(2); 
    let b2 = a2.pow(2); 
} 

Playground

由於兩個都是可能的,明確的類型不能被推斷。

5

and then sum() knows to return an i32

這是你出錯的地方。退房Iterator::sum

fn sum<S>(self) -> S 
    where S: Sum<Self::Item> 

它返回一個泛型類型S它必須實現SumS不是必須匹配Self::Item。因此,編譯器要求您指定將哪些類型歸入。

爲什麼這很有用?從標準庫看看這兩個樣本實現:

impl Sum<i8> for i8 
impl<'a> Sum<&'a i8> for i8 

這是正確的!你可以總結一個迭代器u8迭代器&u8!如果我們沒有這個,那麼這段代碼是行不通的:

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,我們可以通過具有相關類型這將領帶u8 -> u8&'a u8 -> u8做到這一點。

如果我們只有一個關聯類型,那麼目標總和類型總是固定的,我們會失去靈活性。例如,我們也可以爲我們自己的類型實施Sum

在這裏,我們總結u8 s,但增加我們正在求和的類型的大小,因爲它的總和可能會超過u8。這種實現是除了從標準庫中已有的實現:

#[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); 
} 
+1

我想是一個合乎邏輯的步驟;僅僅因爲多個類型想要總結相同的事物,並不意味着必須有另一個類型參數。它可以通過關聯的類型'&'a i8 - > i8'和'i8 - > i8'來解決,依此類推。 – bluss

+0

@bluss非常好的一點! – Shepmaster

+0

謝謝。我的意思是,這不是你的問題,它是在圖書館,但由於這個答案是通過一些步驟來理順它,我想指出。合理化存在的impl可能是快樂之路;-) – bluss

相關問題