拆分结构或重复调用或更好的生锈方法?

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);

}

Playground