在 Rust 中,我正在寻找一种更简洁和惯用的方法来为昂贵的计算定义缓存。
在The Rust Programming Language第二版的第 13 章中,作者为读者留下了一个练习来重构一个结构以返回延迟计算的值。
经过四天的反复试验,我想出了:
use std::collections::HashMap;
#[allow(dead_code)]
struct Cache<T>
where T: Fn(u32) -> u32
{
calculation: T,
internal: HashMap<u32, u32>
}
#[allow(dead_code)]
impl<T> Cache<T>
where T: Fn(u32) -> u32
{
fn new(calculation: T) -> Cache<T> {
Cache {
calculation,
internal: HashMap::new(),
}
}
fn set(&mut self, arg: u32, value: u32) -> u32 {
self.internal.insert(arg, value);
self.get(arg)
}
fn get(&mut self, arg: u32) -> u32 {
self.internal[&arg]
}
fn value(&mut self, arg: u32) -> u32 {
match self.internal.contains_key(&arg) {
true => {
self.get(arg)
},
false => {
self.set(arg, (self.calculation)(arg))
},
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于测试功能:
#[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);
}
Run Code Online (Sandbox Code Playgroud)
我可以改进impl吗?有没有更可接受的方式来写这个?
中set(),self.get(arg)可以简化为value。
get()只需要一个非可变的&self.
get()并且一开始set()看起来并没有那么有用。
该hash_map::EntryAPI可以帮助您简化value()。
fn value(&mut self, arg: u32) -> u32 {
let Self { internal, calculation } = self;
let entry = internal.entry(arg);
*entry.or_insert_with(|| (calculation)(arg))
}
Run Code Online (Sandbox Code Playgroud)然后是次要风格的事情:
您可以使用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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
505 次 |
| 最近记录: |