Caching &引用;应为类型参数,找到类型参数“的引用”;在实现通用缓存结构时

Caching &引用;应为类型参数,找到类型参数“的引用”;在实现通用缓存结构时,caching,rust,closures,Caching,Rust,Closures,在中,编写器实现了一个缓存结构,并留下一些问题供读取器解决,例如: 接受闭包函数上的泛型参数和返回值 允许缓存多个值 我试图解决这些问题,但我被卡住了,无法让它工作 use std::collections::HashMap; use std::hash::Hash; struct Cacher<T, X, Y> where T: Fn(&X) -> &Y, X: Eq + Hash, { calculation: T, r

在中,编写器实现了一个
缓存
结构,并留下一些问题供读取器解决,例如:

  • 接受闭包函数上的泛型参数和返回值
  • 允许缓存多个值
我试图解决这些问题,但我被卡住了,无法让它工作

use std::collections::HashMap;
use std::hash::Hash;

struct Cacher<T, X, Y>
where
    T: Fn(&X) -> &Y,
    X: Eq + Hash,
{
    calculation: T,
    results: HashMap<X, Y>,
}

impl<T, X, Y> Cacher<T, X, Y>
where
    T: Fn(&X) -> &Y,
    X: Eq + Hash,
{
    fn new(calculation: T) -> Cacher<T, X, Y> {
        Cacher {
            calculation,
            results: HashMap::new(),
        }
    }

    fn value<'a>(&'a mut self, arg: &'a X) -> &'a Y {
        match self.results.get(arg) {
            Some(v) => v,
            None => {
                let res = (self.calculation)(arg);
                self.results.insert(*arg, res);
                res
            }
        }
    }
}

我理解这一点,但我想不出一个完美的解决方案来应对整个考验。

您已经声明您的闭包返回了一个引用:

T: Fn(&X) -> &Y,
results: HashMap<X, Y>,
但是,您尝试存储的内容不是引用:

T: Fn(&X) -> &Y,
results: HashMap<X, Y>,
通过一些测试将其取整,这些测试断言它只被调用一次,您就可以开始了。请注意,我们必须在这一过程中做出决定,但他们不是我们唯一可以选择的。例如,我们可以使其在返回时克隆缓存的值


使用std::collections::HashMap;
使用std::collections::hash_map::Entry;
使用std::hash::hash;
结构缓存器
哪里
F:Fn(&I)->O,
I:Eq+Hash,
{
计算:F,
结果:HashMap,
}
嵌入式缓存器
哪里
F:Fn(&I)->O,
I:Eq+Hash,
{
fn新(计算:F)->自{
缓存器{
计算,
结果:HashMap::new(),
}
}
fn值(&mut self,参数:I)->&O{
匹配self.results.entry(arg){
条目::已占用(e)=>e.进入_mut(),
条目::空缺(e)=>{
设res=(自计算)(e.key());
e、 插入(res)
}
}
}
}
#[测试]
fn称_once(){
使用std::sync::atomic::{AtomicUsize,Ordering};
let calls=AtomicUsize::new(0);
让mut c=Cacher::new(|&()|{
calls.fetch_add(1,Ordering::SeqCst);
()
});
c、 价值(());
c、 价值(());
c、 价值(());
assert_eq!(1,calls.load(Ordering::SeqCst));
}

你能解释一下为什么在
F:Fn(&I)->O
中使用
&I
而不是
I
吗?哦,没关系,我想我明白了。我们不知道
I
是否会实现复制特性,因此我们更愿意借用它,而不是获得所有权。@Avishaymatyev您需要通过值的所有权进行推理。如果要将
X
的所有权转移到闭包(
Fn(X)->Y
),则不再需要将其存储在
HashMap
中。同样重要的是,我们已经将参数的所有权转移到了
条目
;我们只能得到一份推荐信。同样,您可以通过要求密钥可复制或可克隆来解决这些决策。