在闭包内部处理可变借用的不可变借用

时间:2019-05-18 22:09:02

标签: rust

作为Rust book的一部分,我实现了带有泛型的Cacher结构。 Cacher包含两个字段:闭包calculation和一个value字段,它是一个HashMap

use std::{collections::HashMap, hash::Hash};

struct Cacher<T, U, V>
where
    T: Fn(U) -> V,
    U: Eq + Hash,
{
    calculation: T,
    value: 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,
            value: HashMap::new(),
        }
    }

    fn value(&mut self, arg: U) -> &V {
        self.value
            .entry(arg)
            .or_insert_with(|| (self.calculation)(arg))
    }
}

我正在努力使用Cacher::value方法,该方法应执行以下操作:

  • 如果value HashMap包含与提供的参数匹配的键,则返回相应的值。

  • 如果value HashMap不包含与参数匹配的键,请执行Cacher的{​​{1}}闭包。使用提供的参数作为键,将此关闭的结果保存在calculation中。

我尝试了各种解决方案,这些解决方案总是导致可变借用和不可变借用之间的冲突。我不确定如何解决该问题。

HashMap

我遇到了编译时错误,因为error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable --> src/lib.rs:27:29 | 24 | fn value(&mut self, arg: U) -> &V { | - let's call the lifetime of this reference `'1` 25 | self.value | ---------- | | | _________mutable borrow occurs here | | 26 | | .entry(arg) 27 | | .or_insert_with(|| (self.calculation)(arg)) | |_____________________________^^__----__________________- returning this value requires that `self.value` is borrowed for `'1` | | | | | second borrow occurs due to use of `self` in closure | immutable borrow occurs here error[E0382]: use of moved value: `arg` --> src/lib.rs:27:29 | 12 | impl<T, U, V> Cacher<T, U, V> | - consider adding a `Copy` constraint to this type argument ... 24 | fn value(&mut self, arg: U) -> &V { | --- move occurs because `arg` has type `U`, which does not implement the `Copy` trait 25 | self.value 26 | .entry(arg) | --- value moved here 27 | .or_insert_with(|| (self.calculation)(arg)) | ^^ --- use occurs due to use in closure | | | value used here after move 是可变借项,而在self.value.entry().or_insert_with()内的闭包中使用self会触发不可变的借用。

由于我正在将or_insert_with()的所有权传递给arg并尝试在闭包内再次使用它,因此value方法也遇到了错误。我应该在这种方法中使用引用吗?如果可以,怎么办?

我从较高的角度理解了这些问题,但是我正在努力寻找解决方法。在尝试读取或写入entry() value时,我该怎么做以防止可变借用和不可变借用的混合使用?

解决方案

我定居的solution

闭包签名更改为HashMap,而Fn(&U) -> V方法更改为:

value

0 个答案:

没有答案