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 这个实现只会浪费内存.