Q:

Difference between nx1 array and n-element array in Julia

In Julia if I define an array with 1 column and n rows it appears to instantiate a "n-element array", I do not understand how this is different from a nx1 array:
julia> a = [1 2 3]
1x3 Array{Int64,2}:
 1  2  3

julia> b = [1;2;3]
3-element Array{Int64,1}:
 1
 2
 3

Confusingly, if I take the transpose twice of a n-element array the return result is a nx1 array:
julia> transpose(transpose(b))
3x1 Array{Int64,2}:
 1
 2
 3

This results in some unexpected (to me) behaviour like:
julia> size(b) == size(transpose(transpose(b)))
false

My questions:

What is the difference between a nx1 array and an n-element array? 
How can I create a nx1 array without doing something like the double-transpose example I gave. 

A:

Quick answers:

An nx1 or 1xn array is a 2-dimensional matrix (that just so happens to have only one row or column), whereas your n-element array is a 1-dimensional column vector. 
I think the simplest way to create a nx1 array literal is taking the transpose of a row vector: [1 2 3]'.  Going the other way, you can flatten any n-dimensional array to a 1-d vector using vec. 

It's much more instructive, though, to think about why this matters.   Julia's type system is designed to be entirely based upon types, not values.   The dimensionality of an array is included in its type information, but the number of rows and columns is not.   As such, the difference between a nx1 matrix and a n-element vector is that they have different types… and the type inference engine isn't able to see that the matrix only has one column. 
To get the best performance from Julia, you (and especially the core language and library designers) want to write functions that are type stable.   That is, functions should be able to deduce what type they will return purely based upon the types of the arguments.   This allows the compiler to follow your variables through functions without losing track of the type… which in turn allows it to generate very highly optimized code for that specific type. 
Now, think about transposes again.   If you want a type stable transpose function, it must return at least a two-dimensional array.   It simply can't do something tricky if one of the dimensions is 1 and still maintain good performance. 
All that said, there's still a great deal of discussion about vector transposes on both the mailing lists and in the GitHub issues.   Here's a great place to get started: Issue #2686: ones(3) ! = ones(3)''.  Or for a much deeper discussion on related issues: Issue #3262: embed tensor-like objects as higher-dimensional objects with trailing singleton dimensions.  Both were eventually superseded and rolled into Issue #4774: Taking vector transposes seriously. 

Update for Julia 0.6: Julia now takes vector transposes very seriously!  The vector transpose now returns a special RowVector type that acts like a 1-row matrix, but with the additional knowledge that there is exactly one row.   It's also a lazy "view" into the original vector.  With the examples in the question, this means that not only is size(b) == size(transpose(transpose(b))) true, but also b'' === b.
It's also a bit easier to specify reshape operations that change dimensionality in Julia 0.6.  A nice answer to question 2 above (creating an nx1 array) is with reshape([1,2,3], :, 1).   The dimension specified by the : is computed to match the length of the source array.