如何解决自我借用地图.or_insert_with?锈(1.11)

mfa*_*ugi 4 dictionary rust

这个片段

use std::collections::HashMap;

struct Foo {
    local_ids: HashMap<i32, i32>,
    last_id: i32,
}

impl Foo {
    fn foo(&mut self, external_id: i32) {
        let id = self.local_ids
                     .entry(external_id)
                     .or_insert_with(||{self.last_id += 1; self.last_id});
    }
}
Run Code Online (Sandbox Code Playgroud)

不行,因为我们不能两次借自己

error: closure requires unique access to `self` but `self.local_ids` is already borrowed [E0500]
Run Code Online (Sandbox Code Playgroud)

这可以在没有第二次密钥查找的情况下修复吗?


这与Rust:HashMap在尝试实现查找或插入时借用问题非常相似,但API已经发生了很大变化.

来自上面的find_with_or_insert_with回答似乎没有映射到当前的api.

Fra*_*gné 5

问题是闭包捕获self,而它只需要捕获对该last_id字段的可变引用.

Rust允许我们对不同的字段进行独立的可变借用,因此我们可以利用它来获得优势,并将last_id字段的可变引用传递给闭包.

use std::collections::HashMap;

struct Foo {
    local_ids: HashMap<i32, i32>,
    last_id: i32,
}

impl Foo {
    fn foo(&mut self, external_id: i32) {
        let last_id = &mut self.last_id;
        let id = self.local_ids
                     .entry(external_id)
                     .or_insert_with(|| { *last_id += 1; *last_id });
    }
}
Run Code Online (Sandbox Code Playgroud)

当我们self.last_id在闭包中使用表达式时,闭包self直接捕获,但Rust没有意识到借用是独立的,所以我们需要更明确.