问题
I am trying to implement a trait that models the euclidean distance between 2 points in an n-dim space. The points are represented as 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()
}
}
Logic tells me that there is no reason for this not to work. As far as I know, the type parser works top to bottom, so all the types should be known. I am using Intellij-Rust and up until the .map(|(xa, xb): (&u32, &u32)|
the compiler got the types just fine, at least I believe it did since it was able to figure out and give type hints about (xa, xb)
before I explicitly specified the type.
As far as I can see, everything goes downhill when I use sum()
. I'm pretty sure I'm missing something since it's pretty unlikely that the type parser wouldn't figure out that the sum of some u32
s is another u32
but it still gives the type must be known in this context
treatment.
What exactly am I missing?
回答1:
I recommend checking the documentation for new functions. Iterator::sum is defined as:
fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
This means that it can be called on any iterator when the return type (S
) can be created from the items of the iterator.
This conceptually allows an array of i8
s to be summed to an i8
, an i16
, i32
, etc. This flexibility comes at a price: you have to specify what type to sum to:
.sum::<MyType>()
You can also stash the result in an explicitly typed variable:
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()
}
This is the exact same as Iterator::collect.
来源:https://stackoverflow.com/questions/48653052/type-must-be-known-in-this-context-when-using-iteratorsum