我想使用函数指针来指向下面这两个函数中的任何一个。当直接调用时,这两个函数都可以正常工作。
当我想使用指针时,它们的类型是不兼容的,尽管它们具有相同的参数a: &'a [T], b: &'a [T],并且都返回f64。
use ndarray::linalg::Dot;
use ndarray::{ArrayView, ArrayBase, RawData};
#[inline]
pub fn euclidean_distance<'a, T>(a: &'a [T], b: &'a [T]) -> f64
where
f64: From<T>,
T: Copy,
{
a.iter()
.zip(b.iter())
.fold(0f64, |acc, (&x, &y)| {
acc + (f64::from(x) - f64::from(y)).powi(2)
})
.sqrt()
}
#[inline]
pub fn cosine<'a, T>(a: &'a [T], b: &'a [T]) -> f64
where
T: Copy,
ArrayView<'a, T, Ix1>: Dot<ArrayView<'a, T, Ix1>, Output = f64>,
{
let x = ArrayView::from(a);
let y = ArrayView::from(b);
x.dot(&y) / (x.dot(&x) * y.dot(&y)).sqrt()
}时,我想使用指向这些函数的指针。
pub struct Model<'a, T>
where
T: Copy,
f64: From<T>,
{
/// Epsilon value - maximum distance between points in a cluster
pub eps: f64,
/// Minimum number of points in a cluster
pub mpt: usize,
distance: fn(a: &'a [T], b: &'a [T]) -> f64,
c: Vec<Classification>,
v: Vec<bool>,
}
impl<'a, T> Model<'a, T>
where
T: Copy,
f64: From<T>,
{
/// Create a new `Model` with a set of parameters
///
/// # Arguments
/// * `eps` - maximum distance between datapoints within a cluster
/// * `min_points` - minimum number of datapoints to make a cluster
pub fn new(eps: f64, min_points: usize, mode: &str) -> Model<T> {
Model {
eps,
mpt: min_points,
c: Vec::new(),
v: Vec::new(),
distance: match mode {
"euclidean" => euclidean_distance,
"cosine" => cosine,
_ => panic!("Unknown Mode {:?}", mode),
},
}
}
}我得到以下错误:“预期的fn指针,找到fn项”。我不明白为什么函数有不同的不兼容类型。
error[E0308]: `match` arms have incompatible types
--> src/dbscan.rs:115:29
|
113 | distance: match mode {
| _______________________-
114 | | "euclidean" => euclidean_distance,
| | ------------------ this is found to be of type `fn(&[T], &[T]) -> f64`
115 | | "cosine" => cosine,
| | ^^^^^^ expected fn pointer, found fn item
116 | | _ => panic!("Unknown Mode {:?}", mode),
117 | | },
| |_____________- `match` arms have incompatible types
|
= note: expected fn pointer `fn(&[T], &[T]) -> _`
found fn item `fn(&[f64], &[f64]) -> _ {dbscan::cosine::<'_, f64>}`发布于 2022-07-19 14:03:09
它只需要几个小的生命周期调整,并且在where中缺少一个impl Model子句。
use ndarray::linalg::Dot;
use ndarray::{ArrayView, Ix1};
struct Classification;
#[inline]
pub fn euclidean_distance<T>(a: &[T], b: &[T]) -> f64
where
f64: From<T>,
T: Copy,
{
a.iter()
.zip(b.iter())
.fold(0f64, |acc, (&x, &y)| {
acc + (f64::from(x) - f64::from(y)).powi(2)
})
.sqrt()
}
#[inline]
pub fn cosine<T>(a: &[T], b: &[T]) -> f64
where
T: Copy,
for<'a> ArrayView<'a, T, Ix1>: Dot<ArrayView<'a, T, Ix1>, Output = f64>,
{
let x = ArrayView::from(a);
let y = ArrayView::from(b);
x.dot(&y) / (x.dot(&x) * y.dot(&y)).sqrt()
}
pub struct Model<T>
where
T: Copy,
f64: From<T>,
{
/// Epsilon value - maximum distance between points in a cluster
pub eps: f64,
/// Minimum number of points in a cluster
pub mpt: usize,
distance: fn(a: &[T], b: &[T]) -> f64,
c: Vec<Classification>,
v: Vec<bool>,
}
impl<T> Model<T>
where
T: Copy,
f64: From<T>,
for<'a> ArrayView<'a, T, Ix1>: Dot<ArrayView<'a, T, Ix1>, Output = f64>,
{
/// Create a new `Model` with a set of parameters
///
/// # Arguments
/// * `eps` - maximum distance between datapoints within a cluster
/// * `min_points` - minimum number of datapoints to make a cluster
pub fn new(eps: f64, min_points: usize, mode: &str) -> Model<T> {
Model {
eps,
mpt: min_points,
c: Vec::new(),
v: Vec::new(),
distance: match mode {
"euclidean" => euclidean_distance,
"cosine" => cosine,
_ => panic!("Unknown Mode {:?}", mode),
},
}
}
}https://stackoverflow.com/questions/73036544
复制相似问题