[英]Rust Cahcer with HashMap Chapter 13
正如第 13 章所建议的,我正在尝试使用 HashMap 来实现缓存器。 与其他一些问题不同,我试图遵循作者采用的方法,并在缓存中使用 Option 作为值。
struct Cacher<T>
where T: Fn(u32) -> u32, //struct needs to know Type of closure(aka calc)
{
calc: T,
value: Option<HashMap<u32, u32>>
}
impl<T> Cacher<T>
where T: Fn(u32) -> u32,{
fn new(calculation: T) -> Cacher<T>{
Cacher {
calc: calculation,
value: None
}
}
fn value(&mut self, arg: u32) -> u32 {
match &mut self.value {
Some(map) => {
let v = map.entry(arg).or_insert((self.calc)(arg));
*v
},
None => {
let mut map = HashMap::new();
let v = map.insert(arg, (self.calc)(arg)).unwrap();
self.value = Some(map);
v
}
}
}
}
代码编译但甚至运行一个简单的:
let mut expensive_res = Cacher::new( |num| {
println!("calculating slowly....{}", num);
thread::sleep(Duration::from_secs(1));
num + 100
});
println!("{}", expensive_res.value(1));
运行它时我会感到恐慌。 线程 'main' 在 '调用Option::unwrap()
on a None
value' 时惊慌失措。 有什么建议么? 为什么 unwrap 这里是 None ? 非常感谢
let mut map = HashMap::new(); let v = map.insert(arg, (self.calc)(arg)).unwrap(); self.value = Some(map); v
我认为您对HashMap::insert
返回的内容感到困惑:它返回键的先前值(如果有)(这就是为什么它是Option
)。
因此,当您刚刚创建了一个空的 map 并且您第一次插入其中时...它返回None
因为那里不可能存在现有值。 因此,此代码路径只能恐慌。
顺便说一句,由于完全不必要的Option<HashMap>
,代码过于复杂:
hash map 最初创建时容量为 0,因此在第一次插入之前不会分配。
因此,抛开这将作为时间优化发挥任何作用的想法不谈,它甚至没有这样做,因为分配被延迟到第一次插入。
在两个代码路径上还有一个问题: Rust 是一种急切的语言,这意味着:
let v = map.entry(arg).or_insert((self.calc)(arg));
相当于:
let mut entry = map.entry(arg);
let default = (self.calc)(arg);
let v = entry.or_insert(default);
所以即使它已经在缓存中,你也可以运行计算,而不是用 memory 换 CPU,这个实现只会浪费 memory。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.