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

时间:2018-02-06 22:32:12

标签: types rust strong-typing

我正在尝试实现一个特征,该特征模拟n-dim空间中2个点之间的欧氏距离。这些点表示为library(tidyverse) tbl <- tribble( ~one, ~two, ~three, ~type, "x", "x", "", "chocolate", "x", "", "", "vanilla", "x", "x", "", "strawberry" ) %>% mutate_at(vars(one:three), function(x) ifelse(x == "", NA_character_, x)) %>% gather(key = "number", value = "x", one:three) %>% rowid_to_column() %>% spread(key = number, value = x) %>% arrange(type) %>% filter(!(is.na(one) & is.na(two) & is.na(three))) %>% select(one, two, three, type) %>% print() # A tibble: 5 x 4 one two three type <chr> <chr> <chr> <chr> 1 x NA NA chocolate 2 NA x NA chocolate 3 x NA NA strawberry 4 NA x NA strawberry 5 x NA NA vanilla

Vec<u32>

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

据我所知,当我使用(xa, xb)时,一切都会走下坡路。我很确定我错过了一些东西,因为类型解析器不太可能发现某些sum()的总和是另一个{{1}但它仍然提供u32治疗。

我到底错过了什么?

1 个答案:

答案 0 :(得分:2)

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

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

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

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