首页 文章

在一个闭包中借用另一个结构域时,可以相互借用一个结构域

提问于
浏览
9

我有一个包含两个字段的结构,我想使用另一个字段(不可变借用)修改一个字段(可变借用),但是我从借用检查器中得到一个错误 .

例如,以下代码:

struct Struct {
    field1: Vec<i32>,
    field2: Vec<i32>,
}

fn main() {
    let mut strct = Struct {
        field1: vec![1, 2, 3],
        field2: vec![2, 3, 4],
    };

    strct.field1.retain(|v| !strct.field2.contains(v));

    println!("{:?}", strct.field1);
}

给出以下错误:

error[E0502]: cannot borrow `strct` as immutable because `strct.field1` is also borrowed as mutable
  --> src/main.rs:12:25
   |
12 |     strct.field1.retain(|v| !strct.field2.contains(v));
   |     ------------        ^^^  -----                   - mutable borrow ends here
   |     |                   |    |
   |     |                   |    borrow occurs due to use of `strct` in closure
   |     |                   immutable borrow occurs here
   |     mutable borrow occurs here

在闭包中使用另一个字段更新一个字段的Rust方法是什么?

2 回答

  • 15

    借用检查器通常可以区分结构的不同字段,但这在闭包(lambdas)中不起作用 .

    相反,借用闭包之外的第二个字段:

    let field2 = &strct.field2;
    strct.field1.retain(|v| !field2.contains(v));
    
  • 3

    这个recent blog post显示了这种问题非常有用的模式:

    有时候,当我想要非常精确的时候,我会以一种风格化的方式编写闭包,这使得它们清晰地捕捉到了什么 . 而不是写| v | ...,我首先介绍一个创建大量局部变量的块,块中的最后一个是移动闭包(移动闭包取得他们使用的东西的所有权,而不是从创建者那里借用它们) . 这样可以完全控制借来的东西和方法 . 在这种情况下,闭包可能看起来像:

    换句话说,借用与封闭物一起限定并移入封闭物中 . 这清楚地表明他们的目的是为封闭提供借来的 Value . 在原始问题的背景下,模式看起来像这样:

    strct.field1.retain({
        let field2 = &strct.field2;
        move |v| !field2.contains(v)
    });
    

    这段代码的一个很好的属性是 field2 的借用在不再使用之后不会留下来 .

相关问题