问题描述
我有以下代码:
use std::collections::{HashMap, HashSet};
fn populate_connections(
start: i32,
num: i32,
conns: &mut HashMap<i32, HashSet<i32>>,
ancs: &mut HashSet<i32>,
) {
let mut orig_conns = conns.get_mut(&start).unwrap();
let pipes = conns.get(&num).unwrap();
for pipe in pipes.iter() {
if !ancs.contains(pipe) && !orig_conns.contains(pipe) {
ancs.insert(*pipe);
orig_conns.insert(*pipe);
populate_connections(start, num, conns, ancs);
}
}
}
fn main() {}
逻辑不是很重要,我正在尝试创建一个函数,它会自行遍历管道.
The logic is not very important, I'm trying to create a function which will itself and walk over pipes.
我的问题是这不能编译:
My issue is that this doesn't compile:
error[E0502]: cannot borrow `*conns` as immutable because it is also borrowed as mutable
--> src/main.rs:10:17
|
9 | let mut orig_conns = conns.get_mut(&start).unwrap();
| ----- mutable borrow occurs here
10 | let pipes = conns.get(&num).unwrap();
| ^^^^^ immutable borrow occurs here
...
19 | }
| - mutable borrow ends here
error[E0499]: cannot borrow `*conns` as mutable more than once at a time
--> src/main.rs:16:46
|
9 | let mut orig_conns = conns.get_mut(&start).unwrap();
| ----- first mutable borrow occurs here
...
16 | populate_connections(start, num, conns, ancs);
| ^^^^^ second mutable borrow occurs here
...
19 | }
| - first borrow ends here
我不知道如何让它工作.一开始,我试图将两个 HashSet
存储在 HashMap
(orig_conns
和 pipes
)中.
I don't know how to make it work. At the beginning, I'm trying to get two HashSet
s stored in a HashMap
(orig_conns
and pipes
).
Rust 不会让我同时拥有可变和不可变变量.我有点困惑,因为这将是完全不同的对象,但我想如果 &start
== &num
,那么我会有两个不同的引用对象(一个可变,一个不可变).
Rust won't let me have both mutable and immutable variables at the same time. I'm confused a bit because this will be completely different objects but I guess if &start
== &num
, then I would have two different references to the same object (one mutable, one immutable).
没关系,但是我怎样才能做到这一点?我想遍历一个 HashSet
并读取和修改另一个.让我们假设它们不是相同的 HashSet
.
Thats ok, but then how can I achieve this? I want to iterate over one HashSet
and read and modify other one. Let's assume that they won't be the same HashSet
.
推荐答案
如果您可以更改数据类型和函数签名,则可以使用 RefCell
来创建 内部可变性:
If you can change your datatypes and your function signature, you can use a RefCell
to create interior mutability:
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
fn populate_connections(
start: i32,
num: i32,
conns: &HashMap<i32, RefCell<HashSet<i32>>>,
ancs: &mut HashSet<i32>,
) {
let mut orig_conns = conns.get(&start).unwrap().borrow_mut();
let pipes = conns.get(&num).unwrap().borrow();
for pipe in pipes.iter() {
if !ancs.contains(pipe) && !orig_conns.contains(pipe) {
ancs.insert(*pipe);
orig_conns.insert(*pipe);
populate_connections(start, num, conns, ancs);
}
}
}
fn main() {}
请注意,如果 start == num
,线程将恐慌,因为这是尝试对同一 HashSet
进行可变和不可变访问.
Note that if start == num
, the thread will panic because this is an attempt to have both mutable and immutable access to the same HashSet
.
根据您的确切数据和代码需求,您还可以使用诸如 Cell
或 原子.它们比 RefCell
具有更低的内存开销,并且对代码生成的影响很小.
Depending on your exact data and code needs, you can also use types like Cell
or one of the atomics. These have lower memory overhead than a RefCell
and only a small effect on codegen.
在多线程情况下,您可能希望使用 Mutex
或 RwLock代码>
.
In multithreaded cases, you may wish to use a Mutex
or RwLock
.
这篇关于从同一个 HashMap 中借用两个可变值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!