Earlier this week I was struggling with an advent of code solution that involved generating a long list of numbers, and then checking some additional conditions about it after a certain number of elements get generated (day 14 if you’re playing).
I made a decent
Iterator for my solution that kept things pretty clean in rust, but it performed orders of magnitude slower than a nearly identical python solution. Digging into why, I was using
Vec.clone() to side-step some borrow checker issues, and it turns out copying the
Vec out on every iteration was the culprit.
I was able to replicate the python solution’s performance by throwing away my
Iterator and instead have an infinite
while-loop calling a mutating method on the struct and continually checking on the state of the list being generated. However, because I was no longer dealing with a clean
Iterator implementation, I ended up introducing a few bugs that took me a while to track down. I was spoiled by keeping things in an
How do I provide visibility of a piece of data from an
Iterator without angering the borrow-checker?
I have a mini-replica of the issue in this playground link. The line that causes the performance hit is the last line in my
fn next(&mut self) -> Option<Vec<i32>> implementation:
Removing the call to
.clone() gives me the following compiler error:
Compiling playground v0.0.1 (/playground) error[E0507]: cannot move out of borrowed content --> src/main.rs:28:14 | 28 | Some(self.current) | ^^^^^^^^^^^^ cannot move out of borrowed content error: aborting due to previous error For more information about this error, try `rustc --explain E0507`. error: Could not compile `playground`. To learn more, run the command again with --verbose.
How do I remove
.clone() to improve my performance, without abandoning the easy-to-use