如何在Rust中为延迟计算的值正确实现缓存结构?

如何在Rust中为延迟计算的值正确实现缓存结构?,rust,Rust,在Rust中,我正在寻找一种更简洁、更惯用的方法来定义用于昂贵计算的缓存 在Rust编程语言第二版的第13章中,作者给读者留下了一个练习,让读者重构结构以返回延迟计算的值 经过四天的反复试验,我得出了以下结论: 使用std::collections::HashMap; #[允许(死代码)] 结构缓存 其中T:Fn(u32)->u32 { 计算:T, 内部:HashMap } #[允许(死代码)] impl缓存 其中T:Fn(u32)->u32 { fn新(计算:T)->缓存{ 缓存{ 计算, 内

在Rust中,我正在寻找一种更简洁、更惯用的方法来定义用于昂贵计算的缓存

在Rust编程语言第二版的第13章中,作者给读者留下了一个练习,让读者重构结构以返回延迟计算的值

经过四天的反复试验,我得出了以下结论:

使用std::collections::HashMap;
#[允许(死代码)]
结构缓存
其中T:Fn(u32)->u32
{
计算:T,
内部:HashMap
}
#[允许(死代码)]
impl缓存
其中T:Fn(u32)->u32
{
fn新(计算:T)->缓存{
缓存{
计算,
内部:HashMap::new(),
}
}
fn集合(&mut self,参数:u32,值:u32)->u32{
self.internal.insert(参数,值);
self.get(arg)
}
fn get(&mut self,arg:u32)->u32{
self.internal[&arg]
}
fn值(&mut self,参数:u32)->u32{
匹配self.internal.contains_键(&arg){
真=>{
self.get(arg)
},
假=>{
自我设置(arg,(自我计算)(arg))
},
}
}
}
对于测试功能:

#[测试]
fn使用不同的值调用{
让mut c=Cache::new(| a | a);
设_v1=c.值(1);
设v2=c.值(2);
断言(v2,2);
}
我可以改进这个
impl
?是否有一种更为可接受的书写方式?

  • set()
    中,
    self.get(arg)
    可以简化为
    value

  • fn value(&mut self, arg: u32) -> u32 {
        let Self { internal, calculation } = self;
        let entry = internal.entry(arg);
        *entry.or_insert_with(|| (calculation)(arg))
    }
    
  • get()
    只需要一个不可变的
    &self

  • get()
    set()
    从一开始似乎并没有什么帮助

  • API可以帮助您简化
    value()

然后是次要的风格:

  • 您可以使用
    Self
    而不是在
    impl
    中重复结构名称

  • 尾随逗号是好的

总共:

use std::collections::HashMap;

pub struct Cache<T>
    where T: Fn(u32) -> u32
{
    calculation: T,
    internal: HashMap<u32, u32>,
}

impl<T> Cache<T>
    where T: Fn(u32) -> u32
{
    pub fn new(calculation: T) -> Cache<T> {
        Self {
            calculation,
            internal: HashMap::new(),
        }
    }

    pub fn value(&mut self, arg: u32) -> u32 {
        let Self { internal, calculation } = self;
        let entry = internal.entry(arg);
        *entry.or_insert_with(|| (calculation)(arg))
    }
}

#[test]
fn call_with_different_values() {
    let mut c = Cache::new(|a| a);
    let _v1 = c.value(1);
    let v2 = c.value(2);
    assert_eq!(v2, 2);
}
使用std::collections::HashMap;
发布结构缓存
其中T:Fn(u32)->u32
{
计算:T,
内部:HashMap,
}
impl缓存
其中T:Fn(u32)->u32
{
pub fn new(计算:T)->Cache{
自我{
计算,
内部:HashMap::new(),
}
}
发布fn值(&mut self,arg:u32)->u32{
设Self{internal,calculation}=Self;
let entry=internal.entry(arg);
*条目。或插入带(| |(计算)(arg))
}
}
#[测试]
fn使用不同的值调用{
让mut c=Cache::new(| a | a);
设_v1=c.值(1);
设v2=c.值(2);
断言(v2,2);
}

也许您想要codereview.SE而不是stackoverflow?这个问题看起来有点太宽泛了。谢谢@SOFe,下次我会记住这一点的。谢谢你抽出时间把这个完整地打印出来。我特别喜欢您演示如何在
Cache::value
中使用对条目的取消引用。