I need a 2D array, but I don’t want to introduce external dependencies like ndarray
, so I want to write one myself.
I could write something like this (playground link):
struct Array<T> {
data: Vec<T>,
columns: usize,
}
impl<T> Array<T> {
fn get_mut(&mut self, i: usize, j: usize) -> &mut T {
&mut self.data[self.columns * i + j]
}
}
fn main() {
let rows = 5;
let columns = 7;
let mut array = Array {
data: vec![0; rows * columns],
columns,
};
assert_eq!(*array.get_mut(3, 4), 0);
}
This one works, but I think this is too complicated, I want something quick and simple, like this (playground link):
fn main() {
let rows = 5;
let columns = 7;
let mut data = vec![0; rows * columns];
let mut array = move |i: usize, j: usize| &mut data[columns * i + j];
assert_eq!(*array(3, 4), 0);
}
But this one does not compile due to lifetime error:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:6:52
|
6 | let mut array = move |i: usize, j: usize| &mut data[columns * i + j];
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 6:21...
--> src/main.rs:6:21
|
6 | let mut array = move |i: usize, j: usize| &mut data[columns * i + j];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `data`
--> src/main.rs:6:52
|
6 | let mut array = move |i: usize, j: usize| &mut data[columns * i + j];
| ^^^^
note: but, the lifetime must be valid for the expression at 8:16...
--> src/main.rs:8:16
|
8 | assert_eq!(*array(3, 4), 0);
| ^^^^^^^^^^^^
note: ...so that pointer is not dereferenced outside its lifetime
--> src/main.rs:8:16
|
8 | assert_eq!(*array(3, 4), 0);
| ^^^^^^^^^^^^
I don’t understand why this happens. I thought a closure is just an instance of some anonymous data structure with captured variables as its members. Why can’t the compiler compile the closure to something like the the Array
structure in my first example?