Search code examples
functionvectorreferencerustborrowing

I want to pass reference of a vector to a function then modify it there and return as vector


I want to pass address of a vector that contains i64 values to a function as argument, then I want my function to modify the vector at its original location and return the modified vector as i64.

I tried to pass mutable reference of the vector to the function and tried to modified it but compiler showing error: a struct with a similar name exists and error: expected type found macro etc.

fn main() {
    let mut my_vector: Vec<i64> = Vec::new();
    my_vector.push(11);
    my_vector.push(12);
    my_vector.push(13);
    println!("{:?}", my_vector);
    let vec_ref: &[vec<i64>] = &my_vector;
    let v2 = change_vector(&mut vec_ref);
    println!("{:?}", v2);
    println!("{:?}", my_vector);
}

fn change_vector(new_vector: &[vec<i64>]) -> Vec<i64> {
    new_vector.push(11);
    new_vector
}

(Playground)

I expect my function change_vector() to receive reference of the location of my_vector, modify it and then return it as vector. Its not happening, compiler showing errors and aborting:

error[E0573]: expected type, found macro `vec`
 --> src/main.rs:7:20
  |
7 |     let vec_ref: &[vec<i64>] = &my_vector;
  |                    ^^^^^^^^
help: a struct with a similar name exists
  |
7 |     let vec_ref: &[Vec<i64>] = &my_vector;
  |                    ^^^
help: use `!` to invoke the macro
  |
7 |     let vec_ref: &[vec!] = &my_vector;
  |                    ^^^^

error[E0573]: expected type, found macro `vec`
  --> src/main.rs:13:32
   |
13 | fn change_vector(new_vector: &[vec<i64>]) -> Vec<i64> {
   |                                ^^^^^^^^
help: a struct with a similar name exists
   |
13 | fn change_vector(new_vector: &[Vec<i64>]) -> Vec<i64> {
   |                                ^^^
help: use `!` to invoke the macro
   |
13 | fn change_vector(new_vector: &[vec!]) -> Vec<i64> {
   |                                ^^^^

I would be grateful for any help.


Solution

  • There are a bunch of issues with your code stemming from incorrect syntax and goals. Let's go through them one by one:

    let mut my_vector: Vec<i64> = Vec::new();
    my_vector.push(11);
    my_vector.push(12);
    my_vector.push(13);
    println!("{:?}", my_vector);
    

    This is fine. my_vector contains [11, 12, 13].

    let vec_ref: &[vec<i64>] = &my_vector;
    

    This is not fine. A reference to Vec<i64> is &Vec<i64>, not a slice. Change this to let vec_ref:&Vec<i64> = &my_vector;. You also do not need this line and if you decide to use this reference later, your code will stop compiling due to a later decision, which we are about to get to...

    let v2 = change_vector(&mut vec_ref);
    

    This is not fine. You cannot take a mutable reference of an immutable reference. It stands to reason. change_vector(&mut my_vector) is fine syntactically, but combined with the previous assignment, is a minefield. You've acquired an immutable reference as vec_ref on the line above; if you do not use vec_ref the compiler will drop it entirely for you; however, if you do decide to use it your code will not compile due to you not being able to hold an immutable and a mutable borrow at the same time.

    fn change_vector(new_vector: &[vec<i64>]) -> Vec<i64> {
    

    This is not fine, for reasons above. It should be fn change_vector(new_vector: &mut Vec<i64>) {.

    The reason the return type changed is that you cannot return an owned Vec from a reference without allocation. If you did want to allocate, then obviously this should be different.

    new_vector.push(11);
    

    This is fine.

    new_vec
    

    With the new return signature, this line is superfluous.

    The corrected code is visible here