当键没有实现克隆特征时记忆

Memoize when key does not implement Clone trait

在下面的惰性记忆示例中,当键未实现 Clone 特征时,如何 return 记忆值?

在下面的实现中,由于键的值已经被移动,我们如何使用给定的键再次从存储中查询值?

当 key 没有实现 clone trait 时,有没有更好的方法来编写这段代码?

struct Cacher<T, Y>
where
    T: Fn(&Y) -> Y,
    Y: Eq + Hash,
{
    store: HashMap<Y, Y>,
    compute: T,
}

impl<T, Y> Cacher<T, Y>
where
    T: Fn(&Y) -> Y,
    Y: Eq + Hash,
{
    fn new(comp: T) -> Self {
        Cacher {
            compute: comp,
            store: HashMap::new(),
        }
    }

    fn get(&mut self, key: Y) -> Option<&Y> {
        if self.store.contains_key(&key) {
            self.store.get(&key)
        } else {
            let value = (self.compute)(&key);
            self.store.insert(key, value);
            self.store.get(&key) //<---- This is problematic
        }
    }
}

使用条目 API:

fn get(&mut self, key: Y) -> &Y {
    if self.store.contains_key(&key) {
        self.store.get(&key).unwrap()
    } else {
        let value = (self.compute)(&key);
        match self.store.entry(key) {
            Entry::Occupied(entry) => unreachable!(),
            Entry::Vacant(entry) => entry.insert(value)
        }
    }
}

但是,此时单独使用条目 API 更好(并且性能更高):

fn get(&mut self, key: Y) -> &Y {
    match self.store.entry(key) {
        Entry::Occupied(entry) => entry.into_mut(),
        Entry::Vacant(entry) => {
            let value = (self.compute)(entry.key());
            entry.insert(value)
        }
    }
}

或者使用组合器:

fn get(&mut self, key: Y) -> &Y {
    self.store.entry(key).or_insert_with_key(&self.compute)
}