【问题标题】:Type must be known in this context when using Iterator::sum [duplicate]使用 Iterator::sum 时,必须在此上下文中知道类型 [重复]
【发布时间】:2018-07-17 02:36:13
【问题描述】:

我正在尝试实现一个特征,该特征对 n 维空间中 2 点之间的欧几里得距离进行建模。这些点表示为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): (&amp;u32, &amp;u32)| 编译器得到了很好的类型,至少我相信它做到了,因为它能够在我明确指定类型之前找出并给出关于 (xa, xb) 的类型提示。

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

我到底错过了什么?

【问题讨论】:

  • 更简单的示例:fn main() { let ans = (0u32..10u32).sum(); } 无法使用 error[E0282]: type annotations needed 进行编译。如果你对sum的调用进行turbo-fish,它将编译。

标签: types rust strong-typing


【解决方案1】:

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

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

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

这在概念上允许将 i8s 的数组求和到 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 完全相同。

【讨论】:

  • 我明白了,这是有道理的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
相关资源
最近更新 更多