Является ли возврат предоставленного аргумента идиоматическим в Rust?

У меня есть код прототипа:

impl MsgTrait for MsgA {
    fn apply_to(&self, state: State) -> State {
        match state {
            State::StateOne(mut state_one) => {
                state_one.common += 1; // just a mutability test
                State::StateOne(state_one)
            },
            _ => {
                state
            }
        }
    }
}

impl MsgTrait for MsgB {
    fn apply_to(&self, state: State) -> State {
        match state {
            State::StateOne(mut state_one) => {
                state_one.common += 2; // just a mutability test
                State::StateOne(state_one)
            },
            State::StateTwo(mut state_two) => {
                state_two.common += 3; // just a mutability test
                State::StateTwo(state_two)
            }
        }
    }
}

// this is a stub for receiving different kinds of messages from the network
fn recv() -> Msg {
    Msg::MsgA(Mega {field_a: 42})
}

fn main() {
    let mut state = State::StateOne(StateOne {common: 0, one_special: 1});
    for _ in 0..100 { // this would be loop, but that makes the playground timeout
        let incoming = recv(); // this would block
        match incoming {
            Msg::MsgA(msg_a) => {
                state = msg_a.apply_to(state)
            },
            Msg::MsgB(msg_b) => {
                state = msg_b.apply_to(state)
            }
        }
    }
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e7ddbbe51ce02c66dc3203bc2ecec104

Чтобы изменить state и сохранить его для следующей итерации цикла, я начал возвращать его из методов.

Это идиоматично в Rust?

Если мне нужно сделать это таким образом, есть ли способ избежать повторной упаковки state_xxx в State::StateXxx(state_xxx) в каждом методе?


person fadedbee    schedule 01.08.2020    source источник
comment
Как правило, это довольно распространено для методов, позволяющих включать шаблоны построителей и другие цепочки методов. Повторная упаковка необходима в зависимости от того, что именно вы хотите сделать. Один из способов избежать многословия — реализовать методы в перечислении, чтобы они сопоставлялись и перепаковывались.   -  person H2O    schedule 01.08.2020
comment
Если вы не хотите перестраивать состояние для каждой мутации, вы можете вместо этого рассмотреть возможность передачи изменяемой ссылки. например, play.rust-lang.org/   -  person possum    schedule 01.08.2020
comment
@possum Это именно то, что я пытался сделать, я просто не включил достаточно mut, чтобы это сработало. Если вы сделаете это ответом, я приму его.   -  person fadedbee    schedule 01.08.2020


Ответы (1)


Если вы не хотите перестраивать состояние для каждой мутации, вы можете вместо этого рассмотреть возможность передачи изменяемой ссылки. например

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=74a8b1113204bc7abe31f9ced0851fd1

person possum    schedule 01.08.2020