【发布时间】:2022-07-19 22:03:09
【问题描述】:
我想使用函数指针来指向下面这两个函数中的任何一个。 直接调用时,这两个函数都按预期工作。
当我想使用指针时,它们的类型不兼容,即使它们具有相同的参数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>}`
【问题讨论】:
-
我相信你想要一个带有
T: Fn(...) -> ....的通用结构 -
你能扩展一下吗?我不明白你的意思。
-
如果你明确地转换函数,它就可以工作。你甚至不需要指定类型,你只需要转换本身:
"euclidean" => euclidean_distance as _, "cosine" => cosine as _,(playground)
标签: rust