Rust Cacher 与 HashMap 第 13 章
Rust Cacher with HashMap Chapter 13
按照第 13 章的建议,我正在尝试使用 HashMap 实现 Cacher。与提出的其他一些问题不同,我正在尝试遵循作者采取的方法并在 Cacher 中使用 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' 在 'called Option::unwrap()
on a None
value' 处恐慌。
有什么建议么?为什么这里解包一个None?
非常感谢
let mut map = HashMap::new();
let v = map.insert(arg, (self.calc)(arg)).unwrap();
self.value = Some(map);
v
我认为您对 HashMap::insert
returns 感到困惑:它 returns 键的先前值,如果有的话 (这就是为什么它是 Option
).
所以当你刚刚创建了一个空地图并第一次插入它时......它 returns None
因为那里 不能 一直是那里的现有值。因此这个代码路径只能恐慌。
顺便说一下,由于 完全没有必要 Option<HashMap>
:
,代码过于复杂
The hash map is initially created with a capacity of 0, so it will not allocate until it is first inserted into.
所以抛开这将作为时间优化的任何角色的想法,它甚至没有这样做,因为分配被延迟到第一次插入。
在两个代码路径上还有一个问题: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);
所以你是 运行 计算 即使它已经在缓存中 ,也就是用内存代替 CPU 这个实现只会浪费内存.
按照第 13 章的建议,我正在尝试使用 HashMap 实现 Cacher。与提出的其他一些问题不同,我正在尝试遵循作者采取的方法并在 Cacher 中使用 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' 在 'called Option::unwrap()
on a None
value' 处恐慌。
有什么建议么?为什么这里解包一个None?
非常感谢
let mut map = HashMap::new(); let v = map.insert(arg, (self.calc)(arg)).unwrap(); self.value = Some(map); v
我认为您对 HashMap::insert
returns 感到困惑:它 returns 键的先前值,如果有的话 (这就是为什么它是 Option
).
所以当你刚刚创建了一个空地图并第一次插入它时......它 returns None
因为那里 不能 一直是那里的现有值。因此这个代码路径只能恐慌。
顺便说一下,由于 完全没有必要 Option<HashMap>
:
The hash map is initially created with a capacity of 0, so it will not allocate until it is first inserted into.
所以抛开这将作为时间优化的任何角色的想法,它甚至没有这样做,因为分配被延迟到第一次插入。
在两个代码路径上还有一个问题: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);
所以你是 运行 计算 即使它已经在缓存中 ,也就是用内存代替 CPU 这个实现只会浪费内存.