I tried to write a special case of vcat which improves type inference to
get around this problem:
f() = vcat(1,[2,3])
@code_warntype f()
gives
Variables:
...
end::ANY
This works:
function my_vcat{T}(x::T, y::AbstractArray{T}) result = Array(T, length(y)+1
) result[1] = x result[2:end] = y return result end
f2() = my_vcat(1,[2,3])
@code_warntype f2()
and gives
Variables: Body: begin # In[4], line 1: return
(Main.my_vcat)(1,(top(vect))(2,3)::Array{Int64,1})::Array{Int64,1}
end::Array{Int64,1}
I wanted to generalize this, but get unexpected behavior:
my_vcat{T}(x::Union{T,Array{T,1}}...) = "foo" # code to be added
my_vcat(1,[2,3],4) # returns "foo" as expected
my_vcat([1,2],3) # throws this exceptions:
LoadError: MethodError: `my_vcat` has no method matching
my_vcat(::Array{Int64,1}, ::Int64)
Closest candidates are:
my_vcat{T}(!Matched::Union{Array{T,1},T}...)
my_vcat{T}(!Matched::Union{Array{T,1},T}...)
my_vcat{T}(::T, !Matched::AbstractArray{T,N})
while loading In[11], in expression starting on line 1
Defining
my_vcat{T}(x::Union{Array{T,1},T}...) = "foo"
(the ordering of Array{T,1} and T has been changed) shows that a third method
for my_vcat has been defined. Actually, every time I rerun the same line, an
additional methods is defined.
methods(my_vcat)
shows
6 methods for generic function *my_vcat*:
- my_vcat*{T}*(x::*T*, y::*AbstractArray{T,N}*) at In[8]:2
- my_vcat*{T}*(x::*Union{Array{T,1},T}...*) at In[1]:1
- my_vcat*{T}*(x::*Union{Array{T,1},T}...*) at In[2]:1
- my_vcat*{T}*(x::*Union{Array{T,1},T}...*) at In[3]:1
- my_vcat*{T}*(x::*Union{Array{T,1},T}...*) at In[4]:1
- my_vcat*{T}*(x::*Union{Array{T,1},T}...*) at In[5]:1
What's going on? And is there a way to achieve this with varargs and Unions
(instead hard-coding every possible combination of T and Array{T})?