使用 Iterator::sum 时,在此上下文中必须知道类型

Type must be known in this context when using Iterator::sum

我正在尝试实现一个特征,该特征对 n-dim space 中两点之间的欧氏距离进行建模。这些点表示为 Vec<u32>.

pub trait Point {
    fn euclidean_to(&self, other: Vec<u32>) -> f64;
}

impl Point for Vec<u32> {
    fn euclidean_to(&self, other: Vec<u32>) -> f64 {
        (self.iter()
            .zip(other.iter())
            .map(|(xa, xb): (&u32, &u32)| (xa - xb).pow(2))
            .sum() as f64)
            .sqrt()
    }
}

逻辑告诉我,这没有理由不起作用。据我所知,类型解析器从上到下工作,因此所有类型都应该是已知的。我正在使用 Intellij-Rust,直到 .map(|(xa, xb): (&u32, &u32)| 编译器得到的类型都很好,至少我相信它做到了,因为它能够在我明确指定之前找出并给出关于 (xa, xb) 的类型提示方式。

据我所知,当我使用 sum() 时,一切都会走下坡路。我很确定我遗漏了一些东西,因为类型解析器不太可能不知道一些 u32s 的总和是另一个 u32 但它仍然给出 type must be known in this context 治疗。

我到底错过了什么?

我建议查看新功能的文档。 Iterator::sum 定义为:

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

这意味着当可以从迭代器的项目创建 return 类型 (S) 时,它可以在任何迭代器上调用。

这在概念上允许将 i8 的数组相加为 i8i16i32 等。这种灵活性是有代价的:您必须指定要求和的类型:

.sum::<MyType>()

您还可以将结果存储在明确类型化的变量中:

fn euclidean_to(&self, other: Vec<u32>) -> f64 {
    let x: u32 = self.iter()
        .zip(other)
        .map(|(xa, xb)| (xa - xb).pow(2))
        .sum();

    (x as f64).sqrt()
}

这与 Iterator::collect 完全相同。