英文:
Rust Borrow Checker Question: Don't know where immutable borrow happens that prevents compiling
问题
我想要从 Rust 的 HashSet 中删除随机元素,但我的实现似乎同时使用了可变借用和不可变借用。我不明白这是在哪里发生的,也不知道如何修复它。
以下是一个简单的程序,它从 HashSet 中随机选择一个元素,然后将其删除。但我得到了以下编译器错误:
错误[E0502]: 无法将 `set` 作为可变引用借用,因为它同时被不可变引用借用了
--> src/main.rs:9:5
|
8 | let num = set.iter().choose(&mut rng).unwrap();
| ---------- 不可变引用在这里出现
9 | set.remove(num);
| ^^^^------^^^^^
| | |
| | 后续调用使用了不可变引用
| 可变引用在这里出现
英文:
I want to remove random elements from a Rust HashSet, but my implementation seems to use a mutable borrow and immutable borrow at the same time. I don't understand where this is happening, or how to fix it.
use std::collections::HashSet;
use rand::seq::IteratorRandom;
fn main() {
let mut set: HashSet<i32> = HashSet::new();
set.insert(2); set.insert(3);
let mut rng = rand::thread_rng();
let num = set.iter().choose(&mut rng).unwrap();
set.remove(num);
}
Here is a simple program that randomly chooses an element from a HashSet and then removes it. But I'm getting the following compiler error:
error[E0502]: cannot borrow `set` as mutable because it is also borrowed as immutable
--> src/main.rs:9:5
|
8 | let num = set.iter().choose(&mut rng).unwrap();
| ---------- immutable borrow occurs here
9 | set.remove(num);
| ^^^^------^^^^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
I don't see how a borrow occurs in set.iter()
or set.remove()
.
答案1
得分: 4
陷阱在于 iter()
返回对元素的引用,因此 num
本身也是一个引用。具体而言,Rust 中的情况如下:
let num: &i32 = set.iter().choose(&mut rng).unwrap();
现在,你有一个名为 num
的引用,它会与后来想要的可变引用发生冲突。
修复方法是在调用 remove()
之前消除引用:
let num: i32 = *set.iter().choose(&mut rng).unwrap(); // 引用已移除
set.remove(&num); // 转换回引用,但是变成了局部变量
这解决了冲突。
如果目标是删除某个随机元素,你还可以使用 retain
和一个函数来删除随机索引,这意味着不需要引用特定元素。
英文:
The trap here is that iter()
returns references to elements, and as such, num
itself is a reference. More specifically, this is what it looks like to Rust:
let num : &i32 = set.iter().choose(&mut rng).unwrap();
Where now you have a reference num
that's lingering and in conflict with the mutable reference you later want.
The fix is to get rid of the reference before calling remove()
:
let num : i32 = *set.iter().choose(&mut rng).unwrap(); // Reference removed
set.remove(&num); // Convert back to reference, but to local variable
That resolves the conflict.
If the goal is to remove some random element, you could also remove a random index with retain
and a function, which means there's no reference to a specific element needed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论