0

I'm trying to turn a matrix A into matrix B where B_11 would be the biggest element of the first row and the smallest element of the second row in a tuple. So the matrix [1,2;3,4] would become [(2,1), (2,2); (4,1), (4,2)].

pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
    let answer = Vec::new();
    println!("matrix: {:?}", input);
    let x: Vec<Vec<_>> = input
        .iter()
        .map(|row| {
            row.iter()
                .map(move |_| {
                    let y = get_column(&input, 0);
                    println!("y is {:?}", y);
                    let x = get_lowest(&y);
                    (get_highest(row), x)
                }).collect()
        }).collect();
    println!("x is {:?}", x);
    answer
}

fn get_highest(row: &Vec<u64>) -> &u64 {
    row.iter().max().unwrap()
}

fn get_lowest(column: &Vec<u64>) -> &u64 {
    column.iter().min().unwrap()
}

fn get_column(matrix: &[Vec<u64>], index: usize) -> Vec<u64> {
    matrix.iter().map(|row| row[index]).collect()
}

I'm getting an error messages when I try to use y:

error[E0597]: `y` does not live long enough
  --> src/lib.rs:11:41
   |
11 |                     let x = get_lowest(&y);
   |                                         ^ borrowed value does not live long enough
12 |                     (get_highest(row), x)
13 |                 }).collect()
   |                 - `y` dropped here while still borrowed
...
17 | }
   | - borrowed value needs to live until here                          

I don't understand why the value y has to live until after it's used. Isn't it enough that it lives until after the get_lowest function? How would I fix this?

mcarton
  • 27,633
  • 5
  • 85
  • 95
Arne Goeteyn
  • 166
  • 9
  • *I don't understand why the value `y` has to live until after it's used* — can you clarify what you mean? How would *any* program work if the variable was not available when it needs to be used? – Shepmaster Aug 20 '18 at 21:29
  • [Why is it discouraged to accept a reference to a String (&String), Vec (&Vec) or Box (&Box) as a function argument?](https://stackoverflow.com/q/40006219/155423) – Shepmaster Aug 20 '18 at 21:55
  • I believe your question is answered by the answers of [Value does not live long enough](https://stackoverflow.com/q/42503296/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 20 '18 at 21:58
  • 1
    TL;DR — you created the `Vec` `y` and then got a reference to the vector via `get_highest` and `get_lowest`. When you exit the closure, `Vec` is destroyed and the references would point at nothing. The compiler is preventing you from making a massive mistake that would lead to memory unsafety in a language like C or C++. – Shepmaster Aug 20 '18 at 22:02

2 Answers2

0

Shepmaster explained it well

TL;DR — you created the Vec y and then got a reference to the vector via get_highest and get_lowest. When you exit the closure, Vec is destroyed and the references would point at nothing. The compiler is preventing you from making a massive mistake that would lead to memory unsafety in a language like C or C++.

Arne Goeteyn
  • 166
  • 9
0

You can use the clone() function to pass new copies of the vectors to the functions get_highest and get_lowest and make the functions return integers and not references with the funciton to_owned().

pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
    let answer = Vec::new();
    println!("matrix: {:?}", input);
    let x: Vec<Vec<_>> = input
        .iter()
        .map(|row| {
            row.iter()
                .map(move |_| {
                    let y = get_column(&input, 0);
                    println!("y is {:?}", y);
                    let x = get_lowest(y.clone());
                    (get_highest(row), x)
                }).collect()
        }).collect();
    println!("x is {:?}", x);
    answer
}

fn get_highest(row: Vec<u64>) -> u64 {
    row.iter().max().unwrap().to_owned()
}

fn get_lowest(column: Vec<u64>) -> u64 {
    column.iter().min().unwrap().to_owned()
}

fn get_column(matrix: &[Vec<u64>], index: usize) -> Vec<u64> {
    matrix.iter().map(|row| row[index]).collect()
}

And as @shepmaster posted, you should avoid using references of Vectors as function parameters.

Miguel Berrío
  • 311
  • 1
  • 7