拆分结构或重复调用或更好的生锈方法?
Splitting structure or duplicate calls or a better way in rust?
以下代码作为我的问题的例子。名为 State
的结构包含许多 Resident
。
现在有一个函数需要同时修改 State 属性 和 Resident 的一个属性。
因为不可能同时获得 State 和该 State 中的一名 Resident 的可变借用。代码无法编译。
我可以想到两种方法来解决它。
一种是只给 modify_state_and_resident() 一个参数:提供了 State 的可变引用。但是我必须在modify_state_and_resident()中再次调用代码在hash map中查找Resident,这很昂贵。
另一种方法是拆分State结构,将其属性和居民拆分为单独的变量。但这会带来其他逻辑问题。毕竟这是一个完整的实体,必须同时在所有地方引用。
不知道有没有更完美的方法解决
#[derive(Debug)]
struct Resident {
age: i32,
name: String,
viewcnt: i32,
}
use std::collections::HashMap;
#[derive(Debug)]
struct State {
version: i32,
residents: HashMap<String, Resident>,
}
// This function cann not be invoked from modify_state_and_resident
fn show_resident(resident: &Resident) {
println!("{:?}", resident);
}
fn modify_state_and_resident(class: &mut State, resident: &mut Resident) {
// I do not want to call hash get again.
class.version = class.version + 1;
resident.viewcnt = resident.viewcnt + 1;
}
#[test]
fn whole_part_mutable() {
let mut s = State {
version: 1,
residents: HashMap::from([
(
String::from("this is a man who named Aaron"),
Resident{age: 18, name: String::from("Aaron"), viewcnt: 0}
),
])};
// get is expensive, I just want to call it when neccessary
let r = s.residents.get_mut("this is a man who named Aaron").unwrap();
// can not call from other function
show_resident(r);
modify_state_and_resident(&mut s, r);
}
您可以解构 State
结构 &mut
以单独访问这两个部分:
fn modify_state_and_resident(version: &mut i32, resident: &mut Resident) {
// I do not want to call hash get again.
*version = *version + 1;
resident.viewcnt = resident.viewcnt + 1;
}
#[test]
fn whole_part_mutable() {
let mut s = State {
version: 1,
residents: HashMap::from([
(
String::from("this is a man who named Aaron"),
Resident{age: 18, name: String::from("Aaron"), viewcnt: 0}
),
])};
let State { version, residents } = &mut s;
// get is expensive, I just want to call it when neccessary
let r = residents.get_mut("this is a man who named Aaron").unwrap();
// can not call from other function
show_resident(r);
modify_state_and_resident(version, r);
println!("{:?}", s);
}
以下代码作为我的问题的例子。名为 State
的结构包含许多 Resident
。
现在有一个函数需要同时修改 State 属性 和 Resident 的一个属性。
因为不可能同时获得 State 和该 State 中的一名 Resident 的可变借用。代码无法编译。
我可以想到两种方法来解决它。 一种是只给 modify_state_and_resident() 一个参数:提供了 State 的可变引用。但是我必须在modify_state_and_resident()中再次调用代码在hash map中查找Resident,这很昂贵。
另一种方法是拆分State结构,将其属性和居民拆分为单独的变量。但这会带来其他逻辑问题。毕竟这是一个完整的实体,必须同时在所有地方引用。
不知道有没有更完美的方法解决
#[derive(Debug)]
struct Resident {
age: i32,
name: String,
viewcnt: i32,
}
use std::collections::HashMap;
#[derive(Debug)]
struct State {
version: i32,
residents: HashMap<String, Resident>,
}
// This function cann not be invoked from modify_state_and_resident
fn show_resident(resident: &Resident) {
println!("{:?}", resident);
}
fn modify_state_and_resident(class: &mut State, resident: &mut Resident) {
// I do not want to call hash get again.
class.version = class.version + 1;
resident.viewcnt = resident.viewcnt + 1;
}
#[test]
fn whole_part_mutable() {
let mut s = State {
version: 1,
residents: HashMap::from([
(
String::from("this is a man who named Aaron"),
Resident{age: 18, name: String::from("Aaron"), viewcnt: 0}
),
])};
// get is expensive, I just want to call it when neccessary
let r = s.residents.get_mut("this is a man who named Aaron").unwrap();
// can not call from other function
show_resident(r);
modify_state_and_resident(&mut s, r);
}
您可以解构 State
结构 &mut
以单独访问这两个部分:
fn modify_state_and_resident(version: &mut i32, resident: &mut Resident) {
// I do not want to call hash get again.
*version = *version + 1;
resident.viewcnt = resident.viewcnt + 1;
}
#[test]
fn whole_part_mutable() {
let mut s = State {
version: 1,
residents: HashMap::from([
(
String::from("this is a man who named Aaron"),
Resident{age: 18, name: String::from("Aaron"), viewcnt: 0}
),
])};
let State { version, residents } = &mut s;
// get is expensive, I just want to call it when neccessary
let r = residents.get_mut("this is a man who named Aaron").unwrap();
// can not call from other function
show_resident(r);
modify_state_and_resident(version, r);
println!("{:?}", s);
}