Idiomatic way to split up methods on &mut self

I have a rather large method that could easily be split up into several, useful, smaller methods but for the issue that the method does its work in a loop.

My code looks like:

fn handle_events(&mut self) {
  for event in self.events.iter() {
    if event.do_thing() {
      // 28 lines of code
    } else {
      // 41 lines of code
    }
  }
}

this works great, but is obviously large and unweildy, especially because the 2 branches of the if are very distinct things, and could be made more concise with some return statements and ? operators (but I can't use them because I need to go to the next loop iteration, and this function doesn't return anything)

I'd like my code to look more like:

fn handle_events(&mut self) {
  for event in self.events.iter() {
    self.handle_event(event);
  }
}

fn handle_event(&mut self, event:&Event){
    if event.do_thing() {
      self.do_thing();
    } else {
      self.do_other_thing(event.other_stuff());
    }
}

fn do_thing(&mut self) {
  // 28 lines of code
}

fn do_other_thing(&mut self, other_stuff: usize) {
  // 41 lines of code
}

but the borrow checker complains. I think I understand why it doesn't like this, and it even makes sense that it shouldn't work.

I've tried using .iter().for_each() and even .fold() but the issue is the borrow of self that allows the loop to happen right?

Surely there's an idiomatic way to do this without having a huge function or e.g. collecting the events into a separate container that isn't part of self.

What's the best way to work around this?

Nevermind. after further reasearch it seems the correct way is to pass the individual fields of the struct to helper methods, rather than passing &mut self

1 Like