Kinda depends on how I interpret your question.
Vector of nD Arrays is basically a list of pointers to arrays, so iterating through it inherently requires following a pointer. This is different from an (n+1)D Array, which can be stored densely in a single contiguous piece of memory. This has fairly significant performance implications, thus I am happy that Julia makes interacting with them explicitly different.
If you do want the more convenient indexing, you can use tools like RecursiveArrayTools.jl
which simplify the indexing for you.
Concerning why cat
added a new index at the end instead of at the beginning, it is because I used dims=4
. By the way, there is a literal version of cat
that is equivalent: [vec_of_arr...;;;;]
where the number of semicolons specifies the dimension along which you want to concatenate. Both cat
and the literal inherit this style from how array literals work in julia: each semicolon adds a new dimension (at the back of the list of indices).
Lastly, the order of indices, I claim, is consistent with the fact that Julia has Fortran style, not C style matrices. I.e. the first index is the fastest growing one, not the last index. E.g. see this example:
julia> a = [1 3; 2 4] # or maybe a = [1; 2;; 3; 4] to make it more explicit
2×2 Matrix{Int64}:
1 3
2 4
julia> a[1], a[2], a[3], a[4] # single-index lookup gives us the contiguous in-memory array
(1, 2, 3, 4)
julia> a[1,1], a[1,2] # modifying the last index causes discontinuous jumps
(1, 3)
julia> a[1,1], a[2,1] # modifying the first index gives neighbors
(1, 2)
Thus, the first index should refer to contiguous neighbors-in-memory, while the last index should refer to big jumps in memory, which hopefully makes what you are observing make sense.