Julia: Shouldn't the compiler infer the vector type in list comprehensions?

Created on 12 Mar 2020  路  4Comments  路  Source: JuliaLang/julia

Regarding the example:

julia> v = [:a=>Float64, :n=>String]
2-element Array{Pair{Symbol,DataType},1}:
 :a => Float64
 :n => String 
julia> a = [s=>Vector{T}() for (s, T) in v]
2-element Array{Pair{Symbol,B} where B,1}:
 :a => Float64[]
 :n => String[] 
julia> eltype(a)
Pair{Symbol,B} where B

Shouldn't the compiler be able to pick up Pair{Symbol,Array{T,1} where {T}} instead of the generic Pair{Symbol,B} where B?

Most helpful comment

Just to have that clear: the type is determined by promotion based on the actual values and has nothing to do with inference.

All 4 comments

Because it would be a wrong result:

julia> Pair{Symbol, Vector{Int}} <: Pair{Symbol, Vector{T} where {T}}
false

julia> Pair{Symbol, Vector{Int}} <: Pair{Symbol, T} where {T}
true

Right, but surely it would be possible to infer it to Pair{Symbol, T} where T<:Vector?

Just to have that clear: the type is determined by promotion based on the actual values and has nothing to do with inference.

Correct, this type is not picked by the compiler, but by promote_typejoin. There are two possible strategies for promoting within a heterogeneous array:

  1. Widen the array element type and leave the elements alone.
  2. Pick a "bigger" concrete type (according to promote_type) and convert all the elements to that type.

Comprehensions use (1):

julia> [x for x in (1,1.0)]
2-element Array{Real,1}:
 1
 1.0

Array literals and concatenation (and lots of other things) use (2).

In general (1) is better, since it avoids converting (and therefore possibly copying) all the elements (in case they are e.g. arrays), and it also preserves more information since you're guaranteed to get out the exact values the comprehension expression generated. In any case, we're not changing this.

Was this page helpful?
0 / 5 - 0 ratings