Surprising result if type annotations are used

Consider the following code:

julia> function foo(T)
           if T == Float64
               v::Vector{Float64} = zeros(5)
           else
               v = T[1, 2, 3, 4, 5]
           end
           v
       end

julia> function bar(T)
           if T == Float64
               v = zeros(5)
           else
               v = T[1, 2, 3, 4, 5]
           end
           v
       end

julia> foo(Float32)
5-element Array{Float64,1}:
 1.0
 2.0
 3.0
 4.0
 5.0

julia> bar(Float32)
5-element Array{Float32,1}:
 1.0
 2.0
 3.0
 4.0
 5.0

I would have expected both foo and bar to behave basically in the same way, since the only difference are type annotations in a branch (which I needed for a more complex but similar example). However, the return types for T == Float32 are different.

  1. Is this expected behavior?
  2. If so, what is the best way to modify foo/bar such that the behavior for T == Float32 is the same as for bar while I can help the compiler in inferring the type of v for T == Float64? In my use case, the compiler isn’t able to figure out that type by itself. Should I just use dispatch on T, e.g.
julia> function test(T::Type{Float64})
           v::Vector{Float64} = zeros(5)
           v
       end
test (generic function with 2 methods)

julia> function test(T::DataType)
           v = T[1, 2, 3, 4, 5]
           v
       end
test (generic function with 2 methods)

julia> test(Float64)
5-element Array{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0

julia> test(Float32)
5-element Array{Float32,1}:
 1.0
 2.0
 3.0
 4.0
 5.0
1 Like

Look what happens if you try to make your initial foo return a Vector{Float32} in the same way that you make it return a Vector{Float64} if the input is Float64:

function foo(T)
    if T == Float64
       v::Vector{Float64} = zeros(5)
    else
       v::Vector{Float32} = T[1, 2, 3, 4, 5]
    end
    v
end
ERROR: syntax: multiple type declarations for "v"

When you force v to be Vector{Float64} in the if part, that type becomes your demand upon v. In your initial bar, the absence of type forcing allows Julia to utilize whichever type is returned within either the if part or the thenpart (because only one of those branches will be used in any one call) as the vector`s element type.

1 Like

Thanks! I went with the solution using dispatch.