Attempt to use a non-constant value in a constant

I'm trying to build an array based on an input array size, so I've the below code:

fn foo(x: &[&Vec<i32>], y: &[&Vec<i32>]) -> Vec<i32> {
    let n = x.len();   // 3
    let array: [Vec<i32>; n] = Default::default();
}

But I got the below error:

error[E0435]: attempt to use a non-constant value in a constant
  --> src\main.rs:51:27
   |
51 |      let array: [Vec<i32>; n] = Default::default();
   |                            ^ non-constant value

This would be called a variable-length array (VLA), but Rust doesn't support this yet.

Use vec![Default::default(); n] or Vec::with_capacity(n) and push to it.

Thanks,
As I need 2D array, I used it as:

fn foo(x: &[&Vec<i32>], y: &[&Vec<i32>]) {
    let n = x.len();   // 3
    let m = x[0].len();  // 3
    let mut array: Vec<Vec<i32>> = vec![vec![Default::default(); n]; m];
}

Vec<Vec> is not a 2D array, but a Jagged Array.

2D array in Rust is implemented with a 1D Vec<i32> type with width*height size, and indexing is done by vec[x + width * y].

1 Like

Can you elaborate more pls.

True 2D arrays "know" and enforce that every row has the same size. A vector of vectors allows every row to have a different size. You may in practice make them same size, but from perspective of the language that doesn't mean anything, and it will still track and check width of every row individually.

Vec of Vec is not a 2D array, but a 1D collection of unrelated 1D arrays.

Rust has an actual 2D array type as [[i32; m]; n], but these arrays can't have size varying at run time.

Rust doesn't have a 2D vec.

But every 1D collection can be tricked into storing 2D data efficiently. The trick is in addressing elements instead of [y][x] as [x + width * y]. This is exactly what happens under the hood in languages that have 2D arrays. The computer memory is 1D, so they all have to do it like this anyway.

8 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.