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})?

Reply via email to