如何在不限制其尺寸的情况下为函数参数指定类型?

时间:2015-01-21 14:40:19

标签: arrays types julia multiple-dispatch

在Julia中,我想将函数参数的类型指定为数组数组。所以我有

function foo{T <: Any}(x::Array{Array{T}})

但如果我在REPL中设置参数x,例如:

x = Array[[0,1],[1,2,3],[0,1,2,4]]

然后它会自动获得以下类型分配(例如),其中包括其尺寸:

x::Array{Array{T,N},1}

以便我收到错误

ERROR: `foo` has no method matching foo(::Array{Array{T,N},1}).

我根本不想限制数组维度,因此我认为解决方案可能与

有关。
function foo{T <: Any, N <: Number}(x::Array{Array{T,N},N})

但这也不起作用。

如何将参数类型指定为数组数组?

1 个答案:

答案 0 :(得分:7)

给定一组数组x = Array[isodd(i) ? [1i,2i] : [1.0i 2.0i] for i=1:10],Julia将其类型报告为Array{Array{T,N},1}。这是欺骗性的,因为它似乎意味着存在一些T和一些N,上述类型将匹配。但事实并非如此:奇数元素的类型为Array{Int,1},而均数为Array{Float64,2}。因此,当您尝试使用类型参数为foo编写方法时:

foo{T,N}(::Array{Array{T,N},1}) = T,N

T的{​​{1}}和N是什么?显然,没有这样的N - 它的都是 1和2!这些子数组的元素不属于x类型 - 它们 AnyInt。这同样适用于Float64,即使在您的示例中您知道Array[[0,1],[0,1,2]]T是一致的,Julia的类型系统也不会......并且您可能会推送非Int的元素载体

有很多方法可以解决这个问题。最好的方法是尝试确保您的数组始终具有具体(或至少是统一的)元素类型,但这并不总是可行的。根据您上面的示例N,您可以改为:x

另一种方法是更改​​功能签名:

x = Array{Int,1}[[0,1],[1,2,3],[0,1,2,4]]

第一个仅适用于由于invariance而具有该类型的情况,而第二个适用于所有阵列数组,包括类型不佳和具体的。

(编辑:最后一点,foo{N}(x::Array{Array,N}) = 1 # Will *only* work for arrays like x above foo{T<:Array, N}(x::Array{T,N} = 2 # Will work for all arrays of arrays 与字面数字不匹配。它会匹配N<:Number子类型的类型,例如{{1} }或Number。目前无法表达类型参数必须是类型Real,超出了N是整数的约定。