尽管存在值,但Entry :: or_insert仍执行

In chapter 13 of the Rust book you implement a Cacher struct for lazy initialization to demonstrate the use of Closures and Functional Programming. As an exercise they encourage the reader to try and create a generic Cacher which can store more than one value. To do so they recommend using a Hashmap.

尝试修改Cacher以保存哈希图,而不是单个值。哈希图的键将是传入的arg值,哈希图的值将是对该键调用闭包的结果。而不是查看self.value是否直接具有Some或None值,value函数将在哈希图中查找arg并返回该值(如果存在)。如果不存在,Cacher会调用该闭包,并将结果值保存在与其arg值关联的哈希图中。      当前Cacher实现的第二个问题是,它仅接受采用u32类型的一个参数并返回u32的闭包。例如,我们可能想要缓存采用字符串切片并返回usize值的闭包结果。要解决此问题,请尝试引入更多通用参数以增加Cacher功能的灵活性。

为了解决此问题,我使用了以下代码:

struct Cacher<T, K, V>
    where T: Fn(K) -> V
{
    calculation: T,
    values: HashMap<K, V>,
}

impl<T, K, V> Cacher<T, K, V>
    where T: Fn(K) -> V,
          K: std::cmp::Eq + std::hash::Hash + Clone,
{
    fn new(calculation: T) -> Cacher<T, K, V> {
        Cacher {
            calculation,
            values: HashMap::new(),
        }
    }

    fn value(&mut self, intensity: K) -> &V {
        self.values.entry(intensity.clone()).or_insert((self.calculation)(intensity))
    }
}

This code compiles and runs, but doesn't serve as a proper Cacher due to the fact that (self.calculation)(intensity) is always executed. Even when the entry exists. What I understand from documentation and examples is that the Entry::or_insert function is only executed if the Entry doesn't exist.

I am aware of the solution to the exercise from question Is it possible to use a single generic for both key and value of a HashMap?, but I would like to know if it's possible to solve the problem the way I'm currently doing it.

Edit: As explained in a comment: or_insert_with does not solve the problem. When trying or_insert_with(|| (self.calculation)(intensity.clone())) I get the following error error[E0502]: cannot borrow self as immutable because it is also borrowed as mutable.

评论