我正在尝试从同一地图中的元素(A)中查找BTreeMap
中元素(B)的值,然后将A的值与B的值进行突变
我知道我可以使用RefCell
来避免“不能借用X是不可变的,因为X也是借来的,因为X是可变的”,但是我想知道是否有一种更惯用的,安全的方法来做到这一点
我已经考虑过尝试存储指向其他元素的指针,但这是行不通的,因为元素的存储位置会随着向BTreeMap
添加元素而移动,因此这是不安全和错误的。 / p>
是否有更好的方法来处理这种模式?
初始尝试
use std::collections::BTreeMap;
struct Map(BTreeMap<String, Foo>);
impl Map {
fn new() -> Self {
Map(BTreeMap::new())
}
fn calc_node(&mut self, name: &str) {
self.0.get_mut(name).unwrap().calc_value(self)
}
}
struct Foo {
name: String,
v: i32,
lookup: String,
}
impl Foo {
fn new(name: String, value: i32, lookup: String) -> Self {
Self {
name,
v: value,
lookup,
}
}
fn calc_value(&mut self, map: &Map) {
self.v = map.0.get(&self.lookup).unwrap().v * 2 // really what I'm trying to do
}
}
fn main() {
let mut map = Map::new();
map.0.insert(
"a".to_string(),
Foo::new("a".to_string(), 1, "b".to_string()),
);
map.0.insert(
"b".to_string(),
Foo::new("b".to_string(), 2, "a".to_string()),
);
println!("{:?}", map.0.get("a").unwrap().v);
map.calc_node("a");
println!("{:?}", map.0.get("a").unwrap().v);
}
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/main.rs:11:50
|
11 | self.0.get_mut(name).unwrap().calc_value(self)
| ------ ---------- ^^^^ immutable borrow occurs here
| | |
| | mutable borrow later used by call
| mutable borrow occurs here
使用RefCell
use std::cell::RefCell;
use std::collections::BTreeMap;
struct Map(BTreeMap<String, RefCell<Foo>>);
impl Map {
fn new() -> Self {
Map(BTreeMap::new())
}
fn calc_node(&self, name: &str) {
self.0.get(name).unwrap().borrow_mut().calc_value(self)
}
}
struct Foo {
name: String,
v: i32,
lookup: String,
}
impl Foo {
fn new(name: String, value: i32, lookup: String) -> Self {
Self {
name,
v: value,
lookup,
}
}
fn calc_value(&mut self, map: &Map) {
self.v = map.0.get(&self.lookup).unwrap().borrow().v * 2
}
}
fn main() {
let mut map = Map::new();
map.0.insert(
"a".to_string(),
RefCell::new(Foo::new("a".to_string(), 1, "b".to_string())),
);
map.0.insert(
"b".to_string(),
RefCell::new(Foo::new("b".to_string(), 2, "a".to_string())),
);
println!("{:?}", map.0.get("a").unwrap().borrow().v);
map.calc_node("a");
println!("{:?}", map.0.get("a").unwrap().borrow().v);
}
我得到正确的结果:
1
4
RefCell
具有运行时成本,理想情况下,我希望能够尽快访问引用的元素。