Nested vec of different type from nested array expression

Hello,

for some unit tests, I need to create deeply nested vectors of usize, for instance Vec<Vec<Vec<Vec<Vec<usize>>>>>.
The vectors also need to contain values, which are hard-coded. The easiest way for me for inputting the values is in the form of arrays, because I can copy-paste the arrays from some other source. For instance:

let boundary_array = [
            [[
                [[0, 3, 2, 1]],
                [[4, 5, 6, 7]],
                [[0, 1, 5, 4]],
                [[1, 2, 6, 5]],
                [[2, 3, 7, 6]],
                [[3, 0, 4, 7]],
            ]],
            [[
                [[8, 11, 10, 9]],
                [[12, 13, 14, 15]],
                [[8, 9, 13, 12]],
                [[9, 10, 14, 13]],
                [[10, 11, 15, 14]],
                [[11, 8, 12, 15]],
            ]],
        ];

However, I actually need a nested vector instead of the array.
The only way I could find to create the desired vectors from an expression is to cast each and every array .to_vec in the expression itself. For instance:

let boundary_vec: Vec<Vec<Vec<Vec<Vec<usize>>>>> =
    [[[[[0, 3, 2, 1].to_vec()].to_vec()].to_vec()].to_vec()].to_vec();

But as you can see, this is very tedious and ugly.
Is there a better way? :slight_smile:

Sounds like a use-case for ndarray.

If all of this is hard-coded, just use the vec![…] macro instead of array literals.

You could use a simple declarative macro for this:

macro_rules! vec_nested {
    ($($([ $($elems:tt)* ]),+ $(,)?)?) => {
        vec![ $( $(vec_nested![$($elems)*]),+ )? ]
    };
    ($($elems:tt)*) => {
        vec![ $($elems)* ]
    };
}

Hm, but then I still would need to write this, which is just as fiddly as calling .to_vec on each array.

let boundary_vec: Vec<Vec<Vec<Vec<Vec<usize>>>>> = vec![vec![vec![vec![vec![0, 3, 2, 1]]]]];

I don't agree. With vec![], you are expressing the intent immediately. It's still just "literals", but vec "literals" instead of arrays.

If you really-really can't stand that, then write a function that recursively converts as many levels as needed, and invoke it once around the top-level array literal.

Edit: I just noticed this:

Don't do that. Write the data to an established serialization format (e.g. npy or even JSON for small arrays) and deserialize it from there.

1 Like

You can use the serde_json::json! macro for that. Simply paste the json inside.

1 Like

Thanks! This solution is the closest to my original intent.

Thanks for the suggestion! I haven't thought about putting this data into files, but it's an obvious choice. And together with @mdHMUpeyf8yluPfXI recommendation, JSON files would make things simple.

You could even create a procedural macro that parses such a data file at compile-time and transforms it to a literal (or a more general expression) that you can then assign to a static item, for example.