Julia:具有抽象参数的数组会导致错误,但具有抽象类型的变量不会';T

Julia:具有抽象参数的数组会导致错误,但具有抽象类型的变量不会';T,julia,Julia,报告说: 不要使用不必要的静态参数。函数签名: foo{T<:Real}(x::T) = ... 我希望这也适用于数组参数。但是,如果我编写以下代码: 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)) 然后我得到以下控制台输出(使用Julia 0.2.1): 那么为什么Julia会对具有抽象类型参数的数组

报告说:

不要使用不必要的静态参数。函数签名:

foo{T<:Real}(x::T) = ...
我希望这也适用于数组参数。但是,如果我编写以下代码:

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))
然后我得到以下控制台输出(使用Julia 0.2.1):


那么为什么Julia会对具有抽象类型参数的数组抛出错误,而对具有抽象类型的变量却不会抛出错误呢

ret3
的情况下,类型参数实际上是必需的,因为
数组{Real}
是一种永远无法构造的类型。Julia的类型参数是不变的。这是一个有点微妙的话题,但关键的事实是,在
ret3
的情况下,
Float64需要一个严格的
数组{Real,2}
,即,一个数组可以容纳任何类型的
Real
变量(而
rand(2,2)
只是
Float64
的数组)

在这种情况下,静态参数不是不必要的:

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

ret3{T从julia 1.2开始,我认为
ret3
的合适类型是:

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

ret3(x::Array{是的,我想这就是答案。但是它需要静态参数,否则看起来就不必要了。为什么Julia没有一个数组类型强制所有元素都是相同的类型呢?我有点困惑,Julia有无数个数组类型强制所有元素都是相同的类型:
Array{Float64}
数组{String}
,等等。你的意思是强制元素具有相同的类型,而不必指定类型是什么?我建议的是数组类型,例如ArrayHomogene{T}其中T可以是抽象类型,如Real或Number,但编译器知道每个元素都是相同的类型,无论该类型是什么。这是一个好问题,但我的猜测是因为它在实践中并没有那么有用-您几乎总是将具体类型的同质数组作为参数传递,而编译器是能够专门处理这个问题。如果数组的元素都被保证为
Real
的某个子类型,那么如果不指定哪个子类型,就没有特别的用处,因为如果没有这些信息,几乎没有结构信息提供给编译器(例如关于内存布局等).我对James的回答做了一个很小的修改:
Array{Real}
是可以构造的,这就是为什么
x::Array{Real}
被用来指代一个独特的具体类型,但是
Real
不能被构造,所以
x::Real
可以被安全地用来指代一个由许多具体类型组成的家族。
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
ret3{T<:Real}(x::Array{T,2}) = x
ret3(x::Array{<:Real,2})