Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

julia

The Julia style guide says the following:

Don’t use unnecessary static parameters. A function signature:

foo{T<:Real}(x::T) = ...

should be written as:

foo(x::Real) = ...

I expected that to apply to array parameters too. However, if I write the following code:

ret1(x::Real) = x
ret2(x::Array{Float64,2}) = x
ret3(x::Array{Real,2}) = x
ret1(1.0)
ret2(rand(2,2))
ret3(rand(2,2))

then I get the following console output (using Julia 0.2.1):

MethodError(ret3,(
2x2 Array{Float64,2}:
 0.841121  0.322133
 0.469432  0.495438,))

So why does Julia throw an error for arrays with abstract type parameters, but not for variables with abstract types?

like image 363
user664303 Avatar asked Apr 27 '14 17:04

user664303


2 Answers

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
like image 173
James Porter Avatar answered Nov 20 '22 22:11

James Porter


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
like image 41
Cristóvão D. Sousa Avatar answered Nov 20 '22 22:11

Cristóvão D. Sousa