Julia: Arrays with abstract parameters cause errors but variables with abstract types don't

In the case of ret3, the type parameter is actually necessary because an Array{Real} is a type that can never be constructed Julia's type parameters are invariant. This is a bit of a subtle topic but the key fact is that while Float64 <: Real is true, Array{Float64} <: Array{Real} is not. This is a bit confusing at first, but this is necessary for the compiler to be able to know the memory layout of function arguments when doing code generation. See the manual for more on this.

So you can dispatch on a Real as in ret1 because when you pass it a Float64, Float64 <: Real is true, whereas in ret3 you are passing it a Array{Float64}, and Array{Float64} <: Array{Real} is not the case, hence the no method error. To fix this, use a type parameter:

julia> ret3{T <: Real}(x::Array{T,2}) = x
ret3 (generic function with 2 methods)

julia> ret3(rand(2,2))
2x2 Array{Float64,2}:
 0.0857132  0.353194
 0.802737   0.717292

In the case of ret3, a strictly Array{Real, 2} is expected, i.e., an array which can hold any kind of Real variables inside (while rand(2,2) is an array of Float64 only).

In this case the static parameter is not unnecessary:

ret3{T<:Real}(x::Array{T,2}) = x

Tags:

Julia