2016-12-07 65 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

相关问题