Rust 中如何实现结构体某一字段是可选函数(带泛型的那种)

Rust 中如何实现结构体某一字段是可选函数(带泛型的那种)

我想简单实现一种缓存,在创建该缓存时,有一个可选的函数,这个函数会在缓存中某一个 key 过期时被回掉,我试了好几种写法,编译无法通过,下面是代码示例

use std::collections::{LinkedList, HashMap};
use std::fmt::{Debug, Formatter};

#[derive(Debug, Default)]
pub(crate) struct Cache<T, F> where F: Fn(String, T) {
    cache: HashMap<String, T>,
    on_evicted: Option<F>,
}

impl<T, F> Cache<T, F> where F: Fn(String, T) {
    fn new() -> Cache<T, F> {
        Cache {
            cache: HashMap::new(),
            on_evicted: None,
        }
    }

    fn new_with_evicted(callback: F) -> Cache<T, F> {
        Cache {
            cache: HashMap::new(),
            on_evicted: Some(callback),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

  #[test]
  fn new() {
        let cache: Cache<String, _> = Cache::new();
  }

执行 cargo check 是可以通过的,但是运行 cargo test 就会报错,因为这个 on_evicted 是可选的,如何在 new 的时候指定泛型,或者不报错就好。哪怕不使用泛型来实现,我这个需求都行!求助了
报错如下:

error[E0284]: type annotations needed: cannot satisfy `<_ as FnOnce<(String, String)>>::Output == ()`
  --> src/lru.rs:34:39
   |
12 |     fn new() -> Cache<T, F> {
   |     ----------------------- required by `lru::Cache::<T, F>::new`
...
34 |         let cache: Cache<String, _> = Cache::new();
   |                                       ^^^^^^^^^^ cannot satisfy `<_ as FnOnce<(String, String)>>::Output == ()`
讨论数量: 3

纠正下自己,不是编译不能通过,而是运行时当使用者不想要这个回调函数的时候,不知道如何去声明

2年前 评论

F: Fn(String, T) 类型参数去掉吧,直接用 &dyn Fn(String, T) -> () 参数类型。
可以看一下这里:stackoverflow.com/questions/363906...

2年前 评论

从代码和说明上看,结构体的泛型参数实现了闭包的Trait。有点绕,简单点理解,即泛型参数实现了多态,那么在实例对象时(消费时)指定泛型参数时,需要动态分配具体的类型。即楼上大哥的写法。

let cache: Cache<String, &dyn Fn(String, String)> = Cache::new();

参考

  1. zhuanlan.zhihu.com/p/109990547
  2. rust-lang.budshome.com/ch17-02-tra...
2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!