16

I am implementing a small program that evaluates the Collatz conjecture. As part of this, I have a function that I call recursively that I want to store the current number being evaluated, determine if it is a odd or even (or terminate if it's just a 1), perform that branch of the conjecture and then call itself with the new number.

To do this, I wanted to pass a vector into this function and push the current number onto that vector, but I am having a tough time understanding how to pass a mutable vector reference.

Here is the code that I have:

fn evaluate_conjecture(number_to_be_evaluated: u64, mut intermediate_results: &Vec<u64>) -> u64 {
    intermediate_results.push(number_to_be_evaluated);

    if number_to_be_evaluated == 1 {
        0
    } else if number_to_be_evaluated % 2 == 1 {
        let odd_step_result = perform_odd_conjecture_step(number_to_be_evaluated);
        evaluate_conjecture(odd_step_result, intermediate_results) + 1
    } else {
        let even_step_result = perform_even_conjecture_step(number_to_be_evaluated);
        evaluate_conjecture(even_step_result, intermediate_results) + 1
    }
}

fn perform_odd_conjecture_step(_: u64) -> u64 {
    unimplemented!()
}

fn perform_even_conjecture_step(_: u64) -> u64 {
    unimplemented!()
}

and here is the relevant part of my main

fn main() {
    let input_number = 42;
    let mut _intermediate_results: Vec<u64>;
    let number_of_steps = evaluate_conjecture(input_number, &_intermediate_results);
}

Here is the error I am getting

error[E0596]: cannot borrow `*intermediate_results` as mutable, as it is behind a `&` reference
 --> src/main.rs:2:5
  |
1 | fn evaluate_conjecture(number_to_be_evaluated: u64, mut intermediate_results: &Vec<u64>) -> u64 {
  |                                                                               --------- help: consider changing this to be a mutable reference: `&mut std::vec::Vec<u64>`
2 |     intermediate_results.push(number_to_be_evaluated);
  |     ^^^^^^^^^^^^^^^^^^^^ `intermediate_results` is a `&` reference, so the data it refers to cannot be borrowed as mutable

How do I pass this vector into the function so I can modify it each time the function is called?

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
mer219
  • 163
  • 1
  • 1
  • 6

1 Answers1

16

&T is an immutable reference.

&mut T is a mutable reference.

Change your &Vec<u64> to &mut Vec<u64> and your &_intermediate_results to &mut _intermediate_results.

This is a thing which is fairly well documented; I suggest you read the documentation if you haven’t — it explains quite a lot. There's a section specifically about mutable references.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • 21
    I'm sorry, I had read both the reference guide and the tutorial on http://doc.rust-lang.org/tutorial.html. The only sample code in those references that have the mut keyword for a function parameter put the mut keyword on the variable name and not the type. And no where is it really clear that in order to pass a mutable variable as a function argument that is also flagged as mut in the prototype, that you must also put the mut keyword in front of the argument when you call the function. Is there some other documentation I should be reading? – mer219 Aug 15 '14 at 16:54
  • 2
    2019 update: see https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html#mutable-references – Steven Kalt Jun 09 '19 at 13:59