【问题标题】:Rust Cacher with HashMap Chapter 13Rust 缓存器与 HashMap 第 13 章
【发布时间】:2022-01-27 12:55:40
【问题描述】:

正如第 13 章所建议的,我正在尝试使用 HashMap 实现缓存器。与其他一些问题不同,我试图遵循作者采取的方法,并在缓存中使用 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));

我在运行它时出现恐慌。 线程“主”在“在 None 值上调用 Option::unwrap()”时出现恐慌。 有什么建议么?为什么 unwrap 这里是 None ? 非常感谢

【问题讨论】:

标签: rust hashmap closures


【解决方案1】:
let mut map = HashMap::new();
let v = map.insert(arg, (self.calc)(arg)).unwrap();
self.value = Some(map);
v

我认为您对HashMap::insert 返回的内容感到困惑:它返回键的前一个值,如果有的话(这就是为什么它是Option)。

因此,当您刚刚创建了一个空地图并第一次将其插入时...它会返回None,因为那里 不可能 那里已经存在一个值。因此这个代码路径只能恐慌。

顺便说一句,由于完全没有必要Option&lt;HashMap&gt;

,代码过于复杂

hash map 最初创建时容量为 0,因此在第一次插入之前不会分配。

因此,抛开这将起到任何作用作为时间优化的想法不谈,它甚至没有这样做,因为分配被延迟到第一次插入。

在两个代码路径上还有一个问题: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,而是浪费内存。

【讨论】:

  • 非常感谢。确实,查看 insert 的文档时,我错过了这一点。同样,考虑到以 0 容量创建的 HashMap 确实意味着在这种情况下使用 Option 毫无意义。并感谢您指出最后一个问题。我不想每次都分配/运行默认值。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 2021-08-23
  • 1970-01-01
相关资源
最近更新 更多