# Inconsistency concerning size(Array) and size(Sparse)

Hi ! I could not find the explanation of why `size([1;1;1])` returns the wrong answer since julia 0.4 -> 1.2.0 while okay for a sparse matrix ? Look:

``````julia> size([1;1;1]) # Expected to have (3,1) or (3,1,) but ok for (3,)
(3,)

julia> (a,b) = size([1;1;1]) # Set 1 to b!
ERROR: BoundsError: attempt to access (3,)
at index [2]
in indexed_next at tuple.jl:21

julia> size([1 1 1]) # good answer !
(1,3)

julia> size(sparse([1;1;1])) # good answer ! Why different answer from dense array???
(3,1)

julia> size(sparse([1 1 1])) # good answer !
(1,3)

julia> size([1;1;1],1) # good answer !
3

julia> size([1;1;1],2) # good answer ! Finally ... !?
1

julia> size([1;1;1],3) # yep I understand that's for simulating other dimensions
1

julia> size([1 1 1],1) # idem for size(sparse([1 1 1]),1)
1

julia> size([1 1 1],2) # idem for size(sparse([1 1 1]),2)
3

julia> size([1 1 1],3) # idem for size(sparse([1 1 1]),3)
1
``````

My problem is that I do `(a,b) = size(M)` with M matrices but if M has one dimension (vector) this is not working. It is sad that `size([1;1;1])` and `size(sparse([1 1 1]))` have different behavior. To be complety consistent `(a,b,c,d) = size(M)` would return (3,1,1,1) in the same way that `size([1;1;1],3)` returns 1. and sader to have to write long version `a = size(M, 1); b = size(M, 2)`

If a Julia maintainer is agreed feel free to reopen https://github.com/JuliaLang/julia/issues/33265

What Julia version are you running? I get:

``````julia> size(sparse([1;1;1]))
(3,)
``````

just as for the dense case.

Here you are comparing a vector with a matrix, why should they behave the same?

Also note that `(3, 1)` is not a â€śgood answerâ€ť. If anything, itâ€™s at most an â€śmatlab answerâ€ť.
AFAICT matlab doesnâ€™t really have anything less than 2D (`size(1)` is `[1, 1]`) but that doesnâ€™t mean thatâ€™s the only correct/good way.

Julia, and many other languages (at least python I believe, didnâ€™t check) allow true lower dimentional arrays and scalars, such object will simply not have a second dimension and so you wonâ€™t see it in `size`. In general, in julia , you should expect `size` on an `AbstractArray{T,N}` (matrix being `N=2` and vector being `N=1`) to return an tuple of length `N`. As long as you see that, what you are seeing is consistent and is simply reflecting the type of the object.

1 Like

Thanks! I was using Julia 1.0 and effectively I just noticed that on Julia 1.2 `size(sparse([1;1;1]))` returns your answer. Good fix

Ok for Vector vs. Matrix but is not it Vector a specialized Matrix for a single dimension?

``````julia> typeof([1;1;1])
Array{Int64,1}

julia> typeof([1 1 1])
Array{Int64,2}
``````

What about my idea of extending `(a,b,c,d,e,f,g) = size(M)` returning the tuple `(3,1,1,1,1,1,1,1)` in the same way that `size(M,n)` always return 1 when n > dim(M).

No and your code clearly shows that.

`Vector` is `Array{T,1}` and `Matrix` is `Array{T,2}` and since `1` is not a specialized `2`, `Array{T,1}` is not a specialized `Array{T,2}`. Both are specialized `Array`, however, since both `1` and `2` are specialized `N`.

Thatâ€™s impossible. Julia does not support dispatch on number of return values (in fact each function can only return one value) and itâ€™s a very good property that itâ€™s not supportedâ€¦

You are right Julia may have its own specific specification but I was talking about consistency between:

• to have the same answer between sparse and dense matrix for Julia. Fredrikekre is right I was working on the wrong version and they make it consistent for Julia 1.2 (bad point for me)
• my second point was the consistency between syntax size(A{T,n}, m) with m > n returning 1 and tuple = size(A) filling all variables inside the tuple when number of variables inside the tuple > m.

Ok thank can you tell me how to write efficiently `a = size(M, 1); b = size(M, 2)` when M is either a vector or a matrix? For me it was shorter way to write (a, b) = size(M). Plus the confusion with the sparse fixed in 1.2

I donâ€™t have 1.0 and I didnâ€™t watch any sparse related issue to remember what the issue was but

1. If `sparse()` is returning a vector thatâ€™s definately a bug in `size`
2. If `sparse()` returns an matrix that wonâ€™t be an inconsistency in `size`.

Iâ€™m just saying that `size(Matrix([1, 2, 3]))` returning a different result than `size([1, 2, 3])` wonâ€™t be inconsistent. It depends entirely on what the function returns.

Thatâ€™s not an inconsistency and is just a convinience. `size(..., n)` wasnâ€™t defined as indexing into the `size` return value. Or equivalently, if you view everything as infinite dim array, `size` is then simply returning the minimum for the type.

And if you still think itâ€™s an inconsistency the solution will be to make `size()` throw an error for out of range dimension. This isnâ€™t as much a big deal though since the current behavior wonâ€™t stop people from doing anything. In fact, it will strictly allow more code to run without error compared to a `size` that does throw.

This is also very different from returning at least 2 dimensions for `size`. Itâ€™s basically the worse solution and makes it hard to distinguish between types.

Sparse is 3 vectors: 2 for axis and 1 for values. `julia> sparse([1;1;1]) 3-element SparseVector{Int64,Int64} with 3 stored entries:`

Iâ€™m just saying that `size(Matrix([1, 2, 3]))` returning a different result than `size([1, 2, 3])` wonâ€™t be inconsistent.

It is fine for me.

`size` is then simply returning the minimum for the type .

it is also fine for me.

Thatâ€™s not inconsistency and is just a convenience.

Ok maybe my terms were not correct. `size([1;1;1],3)` is convenient for tensor with the same reason of yours â€śâ€¦ wonâ€™t stop people from doing anything.â€ť So why not convenience for tuples? This is why I used the term inconsistency (of convenience)

Itâ€™s too long to type, I like Julia for writing small code. Fortunately, I have only two dimensions

That does sounds like a `size` issue.

Because thatâ€™s

1. Impossible (unless you want to return a infinitely long tuple)
2. It actually stops people from doing things since the return value will be missing information about the dimension of the type. (The fact that `size` returns a length `1` tuple tells you that the array is a vector)

Of course you can also invent a type that does the correct thing on indexing. However, that means that people wonâ€™t get a simple tuple back for the size so itâ€™s also â€śstop people from doing thingsâ€ť. Returning something when it otherwise errors doesnâ€™t have this problem since people that just uses `size(A, 1)` wonâ€™t be affected.

This is indeed one of the left over Matlab-ism and I think it just seems benign and useful enough so itâ€™s staying for now.

If you are only dealing with two dimensions, then, really, itâ€™s not longer to type. Also, this kind of thing is why you can define custom functions. You can define your own `size2(a) = size(a, 1), size(b, 1)` if you are actually typing this enough that you see this significantly slowing down your typing.

Thank yuyicha for your patience, Iâ€™m new and I have to catch Julia automatism. Particularity coming from C++ with code row-major way of thinking and where I used to code with fixed-sized Matrix{T, M, N} where MxN are dimensions and Vector{T, N} == Matrix{T, 1, N} (or specialized class for optimization) and where `4Ă—2 Array{Float64,2}` means Matrix4x2 but not where x2 means the 2 of template {T,2}. Finally, itâ€™s maybe not a good practice of mine to write my functions this way `foo(x::Array{T}) where T = ...` thatâ€™s why I finally confused with `size(x)`