Моя цель состояла в том, чтобы реализовать предложенное улучшение структуры кэширования главы 13.1 книги о ржавчине, которая заключается в создании структуры, которая принимает функцию и использует запоминание для уменьшения количества вызовов данной функции. , Чтобы сделать это, я создал структуру с HashMap
struct Cacher<T, U, V>
where T: Fn(&U) -> V, U: Eq + Hash
{
calculation: T,
map: HashMap<U,V>,
}
и двумя методами, одним конструктором и одним, который является ответственным за памятку.
impl<T, U, V> Cacher<T, U, V>
where T: Fn(&U) -> V, U: Eq + Hash
{
fn new(calculation: T) -> Cacher<T,U,V> {
Cacher {
calculation,
map: HashMap::new(),
}
}
fn value(&mut self, arg: U) -> &V {
match self.map.entry(arg){
Entry::Occupied(occEntry) => occEntry.get(),
Entry::Vacant(vacEntry) => {
let argRef = vacEntry.key();
let result = (self.calculation)(argRef);
vacEntry.insert(result)
}
}
}
}
Я использовал перечисление Entry , потому что я не нашел лучшего способа решить, содержит ли HashMap ключ, и - если его нет - вычислить значение и вставить его в HashMap, а также возвращает ссылку на него.
Если я хочу скомпилировать приведенный выше код, я получаю сообщение об ошибке, в котором говорится, что occEntry заимствовано его .get ( ) метод (который мне подходит) и что .get () "возвращает значение, ссылающееся на данные, принадлежащие текущей функции" .
My понимание состоит в том, что компилятор считает, что значение, на которое ссылается occEntry.get () , принадлежит функции value (...) . Но я не должен получить ссылку на значение типа V, который принадлежит HashMap ? Не запутался ли компилятор, поскольку значение принадлежит функции и на короткое время сохраняется как результат ?
let result = (self.calculation)(argRef);
vacEntry.insert(result)
Обратите внимание, что необходимо временно сохранить результат, так как insert метод потребляет ключ и такой argRef больше не действителен. Также я признаю, что подпись значение может быть проблематичной c (см. Изменяемый заимствование из HashMap и жизненного разрешения ), но я попытался избежать черты Copy Bound.
Для быстрого воспроизведения проблемы я добавляю use операторов обязательно. Спасибо за вашу помощь.
use std::collections::HashMap;
use std::cmp::Eq;
use std::hash::Hash;
use std::collections::hash_map::{OccupiedEntry, VacantEntry, Entry};