Quinn's Quibbles: Column-first indexing and iterating through matrices in Julia

One thing I love about Julia is that it uses true vectors, not “n-by-1” arrays that look kinda-sorta like vectors at a distance if you squint.[^1]

You can see this immediately from the type of a vcat call The {Int64,1} reveals the gospel as according to Jules:

julia> vcat(1,2,3,4,5,6,7,8,9)
9-element Array{Int64,1}:
 1
 2
 3
 4
 ⋮
 7
 8
 9

(Credit where credit is due – whoever coded the when big matrices print, great work. It's just lovely. ♥)

Not to worry, though; if you prefer to think in terms of rows rather than columns, and are willing to accept the very slight performance hit, you can also work with hcats:

julia> hcat(1,2,3,4,5,6,7,8,9)
1×9 Array{Int64,2}:
 1  2  3  4  5  6  7  8  9

It's a little less idiomatic, but I promise I won't tell the Pope you're writing your verse in vulgar Latin if you promise not to tell him I've been cutting our holy water with regular well water. What I find disturbing, however, is this:

julia> hvcat(3,          1,2,3,    4,5,6,     7,8,9)
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

hvcat fills in its values row-first. Doesn't this seem odd for a language that gives a (slight) edge to column vectors over row vectors?

Well, actually, no, it doesn't. First off, hvcat starts with an h, not a v. We would expect it to delineate something row-first. More importantly, pretty much everything who's taken linear algebra thinks in “row-by-column” form. And when you want to look into a multidimensional matrix, that's exactly how you should do it:

julia> telephone = hvcat(3,    1,2,3,     4,5,6,     7,8,9)
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> getindex(telephone, 2, 3)
6

julia> # Second row, third column.

But then why is it that when we use only a single index, we still go column-first and not row-first?

julia> telephone = hvcat(3,    1,2,3,     4,5,6,     7,8,9)
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> getindex(telephone, 3) # Third down.
7

julia> getindex(telephone, 7) 
3

Arrrrrrrrrrgh. If you're going to make the 2-index form go row-by-column, then you should make the 1-index form iterate through the rows, not the columns. And I know this sounds like such a minor issue, but these kinds of issues of conceptual integrity are important to me, because they're exactly the kinds of subtly counter-intuitive things that developers will make a mistake on once a year, maybe, but then spend half a day trying to find and debug it. I mean, a change like this doesn't even affect the iteration of n-by-1 and 1-by-m arrays – it just makes dealing with multidimensional arrays more clear.

***

[^1] (Okay, that was mean. No offense to my pure math friends — I just don't like losing sleep over wondering if I'm losing computing cycles over things that the computer thinks are 2D, but really aren't.)