# Why are the inferred types different between collect and comprehension?

``````julia> using ApproxFun

julia> A = Derivative(); B = Multiplication(Fun());

julia> ops = (A, B);

julia> [ops...] |> eltype
Operator{Float64}

julia> collect(ops) |> eltype
Operator
``````

Shouldn’t these lead to the same result?

Note that that is not a comprehension.

The `[]` array constructor promotes argument types, but `collect` and the comprehension evidently do not:

``````julia> [1, 1.0, 1f0]
3-element Vector{Float64}:
1.0
1.0
1.0

julia> collect((1, 1.0, 1f0))
3-element Vector{Real}:
1
1.0
1.0f0

julia> [x for x in ((1, 1.0, 1f0))]
3-element Vector{Real}:
1
1.0
1.0f0
``````

Look at the lowered code for `[1, 1.0, 1f0]`:

``````julia> @code_lowered [1, 1.0, 1f0]
CodeInfo(
1 ─      T = Core._apply_iterate(Base.iterate, Base.promote_typeof, X)
│   %2 = X
│   %3 = Core.tuple(T)
│   %4 = Core._apply_iterate(Base.iterate, Base.getindex, %3, %2)
└──      return %4
)
``````

Note that it is basically `Base.promote_typeof(1, 1.0, 1f0)[1, 1.0, 1f0]`, i.e. `Float64[1, 1.0, 1f0]` thanks to that `promote_typeof`.

4 Likes

``````julia> Meta.@lower [1, 1.0, 1f0]
:(\$(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = Base.vect(1, 1.0, 1.0f0)
└──      return %1
))))

help?> Base.vect
vect(X...)

Create a Vector with element type computed from the promote_typeof of the argument, containing the argument list.
``````

Related to this: