我的目标是在 rust 书第 13.1 章的cacher 结构上实现建议的改进,即创建一个结构,它接受一个函数并使用记忆来减少给定函数的调用次数。为此,我创建了一个带有HashMap的结构
struct Cacher<T, U, V>
where T: Fn(&U) -> V, U: Eq + Hash
{
calculation: T,
map: HashMap<U,V>,
}
Run Code Online (Sandbox Code Playgroud)
和两种方法,一种构造函数和一种负责记忆的方法。
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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我使用了Entry枚举,因为我没有找到更好的方法来确定HashMap 是否包含键,如果不包含键,则计算该值并将其插入到 HashMap 中并返回对它的引用。
如果我想编译上面的代码,我会收到一个错误,它说occEntry是由它的.get()方法借用的(这对我来说很好)并且.get() “返回一个引用当前函数拥有的数据的值”。
我的理解是编译器认为occEntry.get()引用的值归函数value(...) 所有。但是我不应该得到HashMap拥有的 V 类型值的引用吗?编译器是否因为该值归函数所有并暂时保存为结果而感到困惑?
let result = (self.calculation)(argRef);
vacEntry.insert(result)
Run Code Online (Sandbox Code Playgroud)
请注意,需要临时保存结果,因为插入方法消耗了密钥,这样的argRef不再有效。我也承认value的签名可能有问题(请参阅从 HashMap 和生命周期省略中的可变借用),但我试图避免复制特征绑定。
为了快速重现问题,我附加了必要的使用语句。谢谢你的帮助。
use std::collections::HashMap;
use std::cmp::Eq;
use std::hash::Hash;
use std::collections::hash_map::{OccupiedEntry, VacantEntry, Entry};
Run Code Online (Sandbox Code Playgroud)
我们来看看OccupiedEntry::get()的签名:
pub fn get(&self) -> &V
Run Code Online (Sandbox Code Playgroud)
这个签名告诉我们的是,从 获得的引用OccupiedEntry只能和它OccupiedEntry本身一样长。但是,这OccupiedEntry是一个局部变量,因此在函数返回时它会被删除。
我们想要的是一个引用,其生命周期绑定到HashMap的生命周期。二者Entry并OccupiedEntry具有寿命参数('a),其被连接到&mut self在参数HashMap::entry。我们需要一个OccupiedEntry返回 a的方法&'a V。没有这样的方法,但有一个返回'&a mut V: 的方法into_mut。一个可变的参考可以隐式强制转换为一个共享的参考,所以我们需要做的,让你的方法编译是更换get()与into_mut()。
fn value(&mut self, arg: U) -> &V {
match self.map.entry(arg) {
Entry::Occupied(occ_entry) => occ_entry.into_mut(),
Entry::Vacant(vac_entry) => {
let arg_ref = vac_entry.key();
let result = (self.calculation)(arg_ref);
vac_entry.insert(result)
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
539 次 |
| 最近记录: |