Julia在函数定义中的where语句

时间:2019-03-01 17:24:13

标签: types parameters julia

我有一个带有标题的函数

integrateL(f, lb::SArray{Tuple{S},Float64,1, S} where S<:Integer, ub::SArray{Tuple{S},Float64,1, S} where S<:Integer, y::Float64)
    return nothing
end

我不共享该问题的内容,因为问题不在内部,这会造成混淆。该问题是可以重现的。转换变量后,此函数与HCubature.jl包执行半无限多维集成。在参数中,我按照程序包文档中的建议使用StaticArrays来提高性能。要重现该错误,请执行以下操作。

lb = zeros(SVector{1}) #1-element SArray{Tuple{1},Float64,1,1}
ub = ones(SVector{1})  #1-element SArray{Tuple{1},Float64,1,1}
f(y) = y ^2
IntegrateL(f, lb, ub, 5.0)

返回的错误是

no method matching integrateL(::typeof(f), ::SArray{Tuple{1},Float64,1,1}, ::SArray{Tuple{1},Float64,1,1}, ::Float64)

Closest candidates are:
integrateL(::Any, ::SArray{Tuple{S},Float64,1,S} where S<:Integer, ::SArray{Tuple{S},Float64,1,S} where S<:Integer, ::Float64)

所以我的猜测是它不接受ub和lb作为SArray {Tuple {S},Float64,1,S},其中S <:Integer类型,尽管我指定S应该是Integer参数值。我可能会误用这里的“哪里”。请注意,我最初想使用

::SArray{Tuple{Int64},Float64,1,Int64}

在我的函数定义中,但不能。

1 个答案:

答案 0 :(得分:3)

我不知道正确的词来解释这一点,但是where T <: SomeType用于类型。 Tuple{1}中的1不是类型,而是 non-type 参数。

下面的示例可能使事情变得很清楚。

julia> abstract type Pointy{T<:Real} end

julia> Pointy{1.0}
ERROR: TypeError: in Pointy, in T, expected T<:Real, got Float64

julia> Pointy{Float64}
Pointy{Float64}

julia> abstract type Smooth{T} end

julia> Smooth{1.0}
Smooth{1.0}

因此,您的问题的解决方案是仅用where S<:Integer代替where S

此外,您可能想使用SVector{S, Float64}别名而不是SArray{Tuple{S},Float64,1, S}

julia> SArray{Tuple{2},Float64,1, 2} === SVector{2, Float64}
true

请注意,我使用StaticArrays的次数很少,但我认为您的函数过于具体,没有任何好处。例如,您的函数不适用于内置Array。如果您确实需要在函数定义中使用S,则可以像使用length一样使用Array函数。与StaticArrays一样,这样做不会对性能造成任何影响,因为在编译时,对length的调用实际上将由S替换,并且编译器将对循环等进行专门化,就像在原始函数定义中一样