TL;DR I passed some parameter by value to a function, and return some other value (rather than reference), but the compiler complained about a lifetime problem.
The minimum reproduction sample code is placed at
https://github.com/astrojhgu/lifetime_test
I'm implementing a kmeans algorithm.
In order to do that, I need to first create an Inner Product space trait, which represents a type that can calculate inner product between any two vars of this type, based on which distance can be defined.
The definition of the trait is
//an inner product space is firstly linear space,
//so that Add, Sub operators between two elements in the space should be defined.
//Besides, the mul operator to a scalar should be defined.
//So that Add, Sub and Mul traits should be implemented beforehand.
pub trait InnerProdSpace<'a, Scalar>
where
Scalar: Float,
Self: 'a + Sized,
//I don't want the op consume the input values
//so I require &Self, rather Self to impl the Add trait. Same for Sub and Mul.
//As a result, lifetime parameter 'a appeared in the trait's definition.
&'a Self: Add<Output = Self>,
&'a Self: Sub<Output = Self>,
&'a Self: Mul<Scalar, Output = Self>,
{
fn dot(&self, rhs: &Self) -> Scalar;//inner product should be implemented by user
fn distance_to(&'a self, rhs: &'a Self) -> Scalar
{
let d=self-rhs;
d.dot(&d).sqrt()
}
}
Then I write the kmeans function as follows
pub fn kmeans<'a, Scalar, T>(points: Vec<T>, mut seeds: Vec<T>) -> Vec<Vec<T>>
where
T: InnerProdSpace<'a, Scalar>,
&'a T: Add<Output = T>,
&'a T: Sub<Output = T>,
&'a T: Mul<Scalar, Output = T>,
Scalar: Float,
{
let k = seeds.len();
for p in &points {
// ^^^^^^^ borrowed value does not live long enough
let aa:Vec<_> = seeds
.iter().map(|a|{
a.distance_to(p)
}).collect();
}
//place an empty result here to make the compiler happy
vec![vec![]]
}