0

One of the main features of Rust is the borrow checker. Now I found a problem that I cannot solve because I need to mutate after immutable borrow. I am looking for workarounds or alternative solutions for what I want to do, preferably idiomatic methods. The code below is a simplified rewrite of something from C++, where it worked. I am calculating something and saving values in a vector for later analysis. The simplest way is to initialize the "Analysis"-struct with a reference of where to look at for later analysis. Once I am finished calculating new values and storing them in the vector I tell the Analysis-object to check it. I would like to know either how to achieve this or in a more general way, if it is at all a good idea. If not, why is it bad design? (the code below is just an example and does not compile as it is.)

struct Analysis {
    curve_segment: &[f64],
    local_maxima: u32,
    local_minima: u32,
    // ...
}

impl Analysis {
    pub fn new(curve_segment: &[f64]) {
        Analysis {
            curve_segment,
            local_maxima: 0,
            local_minima: 0,
            // ...
        }
    }
    pub fn check_segment(&mut self) {
        for sample in &self.curve_segment {
            // check if maximum or minimum change local_maxima/-minima accordingly
        }
    }
}

fn main() {

    let mut segment: Vec<f64> = vec![0.0; 1000];
    let analysis = Analysis::new(&segment);

    for _ in 0..number_of_segments {
        for i in 0..segment.len() {
            let some_value = // do some calculation;
            segment[i] = some_value; // does not work because segment is already borrowed to 'analysis'.
        }
        analysis.check_segment();
    }
}
exocortex
  • 375
  • 2
  • 9
  • 1
    Your code has several problems, e.g. `Analysis` needs a lifetime parameter. However, I don't really understand the point of the `Analysis` class; couldn't you simple turn that into a single function returning `local_maxima` and `local_minima`? There really isn't a need to store a reference to the data in `Analysis` – in particular if that data is changing all the time. And even with your implementation, you could move the line `let analys = ...` directly above the call to `check_segement()`, and it will work fine. In short, I don't understand what your problem is. – Sven Marnach Oct 05 '22 at 11:47
  • The immutable borrow spans the mutable borrow. – ctrl-alt-delor Oct 05 '22 at 11:57
  • Your code seems wrong: for each segment check the same initial segment. – ctrl-alt-delor Oct 05 '22 at 11:59
  • @SvenMarnach In my actual code I want to store results of the analysis and update them each time "check_segment()" is called. So the better way would be to write it as "check_segment(&segment)"? – exocortex Oct 05 '22 at 12:53
  • @ctrl-alt-delor I am updating the values inside "segment" each time before calling "check_segment()". – exocortex Oct 05 '22 at 12:53
  • 1
    I don't see a good reason to store a persistent reference to the data together with the results of the analysis – even if the data is not changed. If you then want to go ahead and change the data, it makes even less sense. I don't have much context on your code, but from what I've seen I'd say passing a reference to the segment each time it's analyzed makes most sense. – Sven Marnach Oct 05 '22 at 13:41
  • @exocortex yes. I saw that. – ctrl-alt-delor Oct 05 '22 at 16:46

0 Answers0