Hello,
in order to dispatch on a datatype known at runtime, we can use singleton types:
func1(::Type{T},n) where T = Array{T}(n)
which seems to give a type-stable result:
julia> @code_warntype func1(Int32,10)
Variables:
#self#::#func1
#unused#::Any
n::Int64
Body:
begin
return $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Int32,1}, svec(Any, Int64), Array{Int32,1}, 0, :(n), 0))
end::Array{Int32,1}
Here the return type is inferred correctly. I believe the #unused#::Any
is not a problem, though I’m not sure.
I wonder how I can achieve the same type-stable behavior if my func
function doesn’t take the datatype and integer parameters separately, but combined in a tuple. (The eventually intended function should take a variable number of such tuples.) My first try:
func2(spec::Tuple{Type{T},Int}) where T = Array{T}(spec[2])
doesn’t work:
julia> func2((Int32,10))
ERROR: MethodError: no method matching func2(::Tuple{DataType,Int64})
seemingly because the type of (Int32,10)
is Tuple{DataType,Int64}
, not Tuple{Type{Int32},Int64}
. But if I define my func
accordingly,
func3(spec::Tuple{DataType,Int}) = Array{spec[1]}(spec[2])
then the return type can no longer be inferred:
julia> @code_warntype func3((Int32,10))
Variables:
#self#::#func3
spec::Tuple{DataType,Int64}
Body:
begin
return ((Core.apply_type)(Main.Array, (Base.getfield)(spec::Tuple{DataType,Int64}, 1)::DataType)::Type{Array{_,N} where N} where _)((Base.getfield)(spec::Tuple{DataType,Int64}, 2)::Int64)::Array{_,1} where _
end::Array{_,1} where _ # inferred return type is not concrete!
Adding a function barrier, i.e.
function func4(spec::Tuple{DataType,Int}); T,n=spec; func1(T,n); end
also doesn’t help.
Is it possible to properly dispatch on the singleton type inside the tuple? How? Thanks.