1:n, (1:n)', and (1:n)''


#1

Hello. I am curious about the following behavior of the transposition operator associated with the UnitRange data type. Let n be a natural number. Now, the type of 1:n is UnitRange{Int64}.
But why does (1:n)' become a row vector (or more precisely, Matrix{Int64} type of size 1 x n) while (1:n)'' become a column vector (or more precisely, ``Matrix{Int64}type of size n x 1)? Why does the single transposition applied to1:n``` turn it into a row vector? This behavior is mysterious to me.
Thanks!
BVPs


#2

I’m happy to answer your questions here, but first I’m curious about your expectations… given x = (1:n)', what kind of thing do you expect x to be? What kinds of operations do you want to perform on x?


#3

If anything is mysterious then it is the fact that (1:n)' becomes a row vector. (i.e. that 1:n is interpreted as a columns vector). But since a row vector is just a matrix, transposing it will remain a matrix; this seems very natural to me.


#4
  • (1:n)' returns a 1×n row-matrix because we’ve chosen to treat one-dimensional arrays as though they are one-column matrices in many operations. This is actively a point of design and research — and possible change — which is why I wanted to hear about your expectations before explaining the current design. It’s a dense array of Ints because we don’t have any specialized types that can more compactly represent ranges of size 1×n.

  • The transpose of a 1×n row-matrix is a n×1 column-matrix. Conversely, the transpose of a n×1 column matrix is a 1×n row-matrix. This is a rather sensible definition of transpose. We don’t want to do something special for dimensions that happen to be one because that would be type-unstable (returning either a one- or two-dimensional container depending upon the size of the argument).

These two choices lead directly to the relatively unsatisfactory result that the double transpose of a one-dimensional array is not equal to itself (v != v''). There’s lots more you can read here if you’re interested.


#5

Thanks for your quick reply! In MATLAB x=1:n is simply a row vector (i.e., a matrix of size 1 x n). But, since julia is not MATLAB, I cannot expect that happens. Hence, most naturally, I want to see x=1:n as a Vector{Int64}. My guess is that UnitRange{Int64} is a specialization of Vector{Int64}. Correct me if I am wrong. Suppose this is true. Then, why the transposition of the Vector data turns into a row vector? Is this because a Vector data type is weakly viewed as a column vector? Or is it truly a column vector?


#6

Thanks for your explanation! I now understand that it’s a touchy issue. In particular, the fact v != v'' may invite a potential problem eventually.


#7

Yup, a lot of this falls out from the fact that Matlab’s behaviors don’t mesh well with a stronger type system that differentiates scalars from one-dimensional containers and two-dimensional containers. In fact, even scalars in Matlab are implicitly 1x1 matrices:

>> x = 1;
   x(end+1) = 2;
   x
x =
     1     2

>> x(end+1, :) = [3,4]
x =
     1     2
     3     4

There are some surprising indexing rules in Matlab because of this, “iteration” is bizarre, and length is really quite strange, but for the most part it works surprisingly well.

In Julia, we have completely separate behaviors for scalars and arrays. This choice is a key advantage for the compiler and allows Julia to perform much more aggressive optimizations. We even have different behaviors for one-dimensional and two-dimensional arrays, because the former allow for efficiently push!-ing and pop!-ing elements. Changing the size of a two-dimensional array requires copying memory in many cases.