首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >预期fn指针,找到fn项

预期fn指针,找到fn项
EN

Stack Overflow用户
提问于 2022-07-19 12:03:16
回答 1查看 130关注 0票数 -1

我想使用函数指针来指向下面这两个函数中的任何一个。当直接调用时,这两个函数都可以正常工作。

当我想使用指针时,它们的类型是不兼容的,尽管它们具有相同的参数a: &'a [T], b: &'a [T],并且都返回f64

代码语言:javascript
复制
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()
}

时,我想使用指向这些函数的指针。

代码语言:javascript
复制
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项”。我不明白为什么函数有不同的不兼容类型。

代码语言:javascript
复制
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>}`
EN

回答 1

Stack Overflow用户

发布于 2022-07-19 14:03:09

它只需要几个小的生命周期调整,并且在where中缺少一个impl Model子句。

代码语言:javascript
复制
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),
            },
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73036544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档