In the example below, why can the type of x
be inferred for S1
but not for S2
? Is this behavior documented anywhere or is it a bug?
julia> struct S1
x::Vector{Int}
end
julia> struct S2{N}
x::Vector{Int}
y::Vector{SVector{N,Int}}
end
julia> S1([])
S1(Int64[])
julia> S2([], SVector{3,Int}[])
ERROR: MethodError: no method matching S2(::Array{Any,1}, ::Array{SArray{Tuple{3},Int64,1,3},1})
Closest candidates are:
S2(::Array{Int64,1}, ::Array{SArray{Tuple{N},Int64,1,N},1}) where N at REPL[3]:2
Stacktrace:
[1] top-level scope at REPL[5]:1
julia> S2(Int[], SVector{3,Int}[])
S2{3}(Int64[], SArray{Tuple{3},Int64,1,3}[])
[]
is a vector of zero length. SVector{3,Int}[]
asks for a StaticVector with 3 Ints
to be obtained from a vector of 0 Ints
.
Use @SVector([1,2,3])
if that’s what you want.
julia> s2 = S2([1,2,3],[@SVector([1,2,3,4])])
S2{4}([1, 2, 3], SArray{Tuple{4},Int64,1,4}[[1, 2, 3, 4]])
also, you do not need to wrap the SVector in a Vector
struct S2{N}
x::Vector{Int}
y::SVector{N,Int}
end
julia> S2([1,2], @SVector([2,4])
S2{2}([1,2], [2,4])
This is a bit subtle because the default outer constructor looks a bit different for the parametric vs non-parametric cases. I’m a bit hazy on this myself as the documentation at https://docs.julialang.org/en/v1/manual/constructors/index.html#Parametric-Constructors-1 isn’t very explicit about the exact form for the default outer constructor.
In this particular case, I think the default outer constructor for S2
is
S2(x::Array{Int64,1}, y::Array{SArray{Tuple{N},Int64,1,N},1}) where {N} = S2{N}(x,y)
Whereas for S1
, the default outer constructor is
S1(x) = S1(convert(Vector{Int}, x))
So you can see why one case will match and the other will not. It does seem inconvenient though that the default outer constructor for S2
doesn’t match and just use convert. The following issue suggests that it was to make it harder to accidentally introduce infinite recursion when defining extra constructors: https://github.com/JuliaLang/julia/issues/10641.
1 Like
Just to clarify, I did want y
to be a zero length Vector
of SVector{3,Int}
s.
I think Chris’s response about S1
using convert
clears my confusion.