Last active
August 12, 2024 19:32
-
-
Save matthewjberger/2c95d97a6984de1f9452ccef2a4bf0a4 to your computer and use it in GitHub Desktop.
Alternatives to drain to preventable multiple mutable refs to self
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::VecDeque; | |
#[derive(Debug, Clone)] | |
struct Event(u32); | |
struct Context { | |
queued_events: VecDeque<Event>, | |
} | |
impl Context { | |
fn new() -> Self { | |
let mut queued_events = VecDeque::new(); | |
queued_events.push_back(Event(1)); | |
queued_events.push_back(Event(2)); | |
queued_events.push_back(Event(3)); | |
Context { queued_events } | |
} | |
fn process_event(&mut self, event: &Event) { | |
println!(" Processing event: Event({})", event.0); | |
self.some_other_method(); | |
} | |
fn some_other_method(&mut self) { | |
println!(" Called some_other_method"); | |
} | |
fn process_events_drain(&mut self) { | |
println!("1. Using drain() - This will not compile:"); | |
// Uncommenting the next line will cause a compilation error | |
// self.queued_events.drain(..).for_each(|event| self.process_event(&event)); | |
// Error: cannot borrow `self` as mutable more than once at a time | |
println!(" (Compilation error if uncommented)"); | |
} | |
fn process_events_clone(&mut self) { | |
println!("\n2. Using clone (works but maybe inefficient):"); | |
let events = self.queued_events.clone(); | |
for event in &events { | |
self.process_event(event); | |
} | |
self.queued_events.clear(); | |
println!(" Queue size: {}", self.queued_events.len()); | |
} | |
fn process_events_pop_front(&mut self) { | |
println!("\n3. Using while let with pop_front():"); | |
while let Some(event) = self.queued_events.pop_front() { | |
self.process_event(&event); | |
} | |
println!(" Queue size: {}", self.queued_events.len()); | |
} | |
fn process_events_take(&mut self) { | |
println!("\n4. Using std::mem::take():"); | |
let events = std::mem::take(&mut self.queued_events); | |
for event in &events { | |
self.process_event(event); | |
} | |
println!(" Queue size: {}", self.queued_events.len()); | |
} | |
fn process_events_replace(&mut self) { | |
println!("\n5. Using std::mem::replace() with new():"); | |
let events = std::mem::replace(&mut self.queued_events, VecDeque::new()); | |
for event in &events { | |
self.process_event(event); | |
} | |
println!( | |
" Queue size after processing: {}", | |
self.queued_events.len() | |
); | |
} | |
} | |
fn main() { | |
let mut context = Context::new(); | |
context.process_events_drain(); | |
context = Context::new(); | |
context.process_events_clone(); | |
context = Context::new(); | |
context.process_events_pop_front(); | |
context = Context::new(); | |
context.process_events_take(); | |
context = Context::new(); | |
context.process_events_replace(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment