Henri.D
Henri.D

Reputation: 145

Julia where statement in function definition

I have a function with the header

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

I do not share the content for the issue is not inside and it would be confusing. The issue is reproducible as is. This function performs a semi-infinite multi-dimensionnal integration with HCubature.jl package after transforming the variables. In the arguments I use StaticArrays as advised in the package documentation for performances. To reproduce the error do as follows.

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)

the error returned is

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)

So my guess is that it is not accepting ub and lb as SArray{Tuple{S},Float64,1,S} where S<:Integer types eventhough I specified that S should be an Integer parametric value. I am probably missusing 'where' here. Note that I originally wanted to use

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

in my function definition but couldn't.

Upvotes: 2

Views: 702

Answers (1)

hckr
hckr

Reputation: 5583

I do not know the right words to explain this but where T <: SomeType is used for types. 1 in Tuple{1} is not a type, but rather a non-type parameter.

The following example might make things clear.

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}

The solution to your question, therefore, is to replace where S<:Integer with just where S.

In addition, you might want to use SVector{S, Float64} alias instead of SArray{Tuple{S},Float64,1, S}.

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

As a side note, I haven't used StaticArrays much but I think your function is overly-specific for no benefit. Your function, for example, won't work with built-in Arrays. If you really need S in your function definition, you might just use length function just as you would with Arrays. There will be no performance penalty of doing so with StaticArrays, since the call to length will actually be replaced by S in compilation time and the compiler will specialize your loops etc. just as in your original function definition.

Upvotes: 4

Related Questions