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 Julia's type parameters are invariant. This is a bit of a subtle topic but the key fact is that while Array{Real}
is a type that can never be constructedFloat64 <: 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