Multidimensional array syntax

Are there any articles explaining the multidomensional array syntax at a level a complete idiot (me) can understand?

Do you have in mind something like this? (not Julia though)

Do you mean the new syntax for multidimensional array literals, with the semicolons? I thought the 1.7 release highlights did a pretty good job of it. (Though now I look back at it, I see they jump to slightly more complicated uses before explaining the basic idea/usage.)

The simple rule is “N semicolons = concatenation in the Nth dimension”. Let us know if you have any specific confusions, or any examples that don’t make sense (or in case you weren’t talking about this at all!).

1 Like

I felt a bit confused when I read through the highlights the very first time. The confusing point is after the example of [1 2; 3 4], the next example is [1 2;;; 3 4]. At that time I wondered how about the two-semicolon case?

1 Like

AFAIU, the key point to note is that a space is equivalent to two semicolons, e.g. [1 2;;; 3 4] == [1;; 2;;; 3;; 4].

3 Likes

Wow, a space equals two semicolons. That never occurred to me, and it points to the source of the confusion: we conventionally use a row-major representation for literal matrices , even though the internal represtation is column-major.

Maybe the docs should include the example [1 ; 3 ;; 2; 4] as the consistent if unusual column-major literal for the matrix [1 2 ; 3 4]. I’ll see if I can put in a PR.

1 Like

Just be aware that they are not completely interchangeable which seems to have to do with evaluation order. Space seems to be evaluated first, and otherwise smaller number of semicolons are evaluated first

julia> [1 2; 3 4]
2Ă—2 Matrix{Int64}:
 1  2
 3  4

julia> [1;;2;3;;4] # Similar evaluation as [1;;[2;3];;4], does not work
ERROR: ArgumentError: argument 3 has a mismatched number of elements along axis 1; expected 0, got 1
Stacktrace:
 [1] _typed_hvncat_shape(#unused#::Type{Int64}, shape::Tuple{Tuple{Int64, Int64, Int64}, Tuple{Int64}}, row_first::Bool, as::NTuple{4, Int64})
   @ Base ./abstractarray.jl:2431
 [2] _typed_hvncat(::Type, ::Tuple{Tuple{Int64, Int64, Int64}, Tuple{Int64}}, ::Bool, ::Int64, ::Vararg{Int64})
   @ Base ./abstractarray.jl:2381
 [3] _hvncat(::Tuple{Tuple{Int64, Int64, Int64}, Tuple{Int64}}, ::Bool, ::Int64, ::Vararg{Int64})
   @ Base ./abstractarray.jl:2134
 [4] hvncat(::Tuple{Tuple{Int64, Int64, Int64}, Tuple{Int64}}, ::Bool, ::Int64, ::Vararg{Int64})
   @ Base ./abstractarray.jl:2129
 [5] top-level scope
   @ REPL[2]:1

julia> [[1;;2];[3;;4]] # Works because we force the evaluation order
2Ă—2 Matrix{Int64}:
 1  2
 3  4

julia> [1;3;;2;4] # Also works because we flip the order we insert the numbers in
2Ă—2 Matrix{Int64}:
 1  2
 3  4
2 Likes

Sorry :slight_smile:

precisely, which makes the matrix (row) direction the 2nd dimension, thus 2 ;

2 Likes

Yes, the order of precedence is [space] > ; > ;; > ;;; > ;;;; > [...].

The reason for that is it makes things much more complicated to parse if you can’t depend on reading that structure in the syntax.

And " " and ;; cannot be mixed, because that tells Julia that you’re either writing it in row-first or column-first mode, so the method can iterate over the arguments correctly.

1 Like

Yes. ; concatenates along the first dimension, <space> or ;; concatenates along the second dimension, ;;; concatenates along the third dimension, etc.

2 Likes

The documentation might be a better primer than the blog post, as it builds from simple to more complex:

https://docs.julialang.org/en/v1/manual/arrays/#man-array-concatenation

4 Likes