Array of type Any vs Union

question

#1
julia> [ "s", 1]
2-element Array{Any,1}:
  "s"
 1   

julia> [ "s", 1] :: Array{Union{String, Int},1}
ERROR: TypeError: typeassert: expected Array{Union{Int64,String},1}, got Array{Any,1}

Im thinking at this point that I probably have to promote the “s” and 1 as actual elements of a specific Union type but I can’t make it work.

julia> foo = Union{Int, String}
Union{Int64,String}

julia> [ "s", 1]
2-element Array{Any,1}:
  "s"
 1   

julia> [ "s"::foo, 1::foo]
2-element Array{Any,1}:
  "s"
 1   

julia> [ "s"::foo, 1::foo] :: Array{foo,1}
ERROR: TypeError: typeassert: expected Array{Union{Int64,String},1}, got Array{Any,1}


#2

If you really want this, you can construct the Array{Union{String, Int}} directly:

julia> Union{String, Int}["s", 1]
2-element Array{Union{Int64,String},1}:
  "s"
 1

or

julia> convert(Vector{Union{String, Int}}, ["s", 1])
2-element Array{Union{Int64,String},1}:
  "s"
 1

But can I ask what you need this for? I think it’s pretty unusual to explicitly declare a Vector{Union...}.


#3

Hi,
Thanks for that.

i was trying to generate an array of two types, let’s say A and B, and just wanted to make sure my arguments to the functions handling this vector are explicitly typed.

However i realized that i’m not solving my problem correctly.

what i should really be doing, I think, is something like

abstract A
type B <: A end
type C <: A end

Vector{A,1}

Right ?


#4

It depends a bit on what you want your function to do. If you want your function to take a vector of all Bs or all Cs, then you can write:

function f(x::Union{Vector{B}, Vector{C}})
    ...
end

(note: you can either have a Vector{A} or an Array{A, 1} (they’re the same), but not a Vector{A, 1} (that’s not a thing)).

If you want to mix and match Bs and Cs within the same vector, then you can write:

function f{T <: A}(x::Vector{T})
    ...
end

or, you can use Julia v0.6’s new syntax to write:

function f(x::Vector{<:A})
    ...
end

But note that having a vector that mixes elements of type B and C is going to be slower, since Julia won’t know the exact type of each element of the vector. For more discussion of that situation, check out this thread: How to make a vector of parametric composite types?


#5

Yes, the idea is that I have both B & C types in the vector.

This is actually an intermediate step.

The source vector is mixed, and in the next step the vector is separated into two vectors of B and C.

I’m thinking about the original problem a little more ,because I’m still thinking that maybe I’m not solving it in the best way.

Meanwhile I sort of took a detour into why I couldn’t seem to create a vector of a Union.


#6

While every application will be different, for me when there is no clear reason to give a Vector a particular abstract eltype, I fall back to Vector{Any} for performance reasons: this avoids overspecialization at the expense of less type information for the compiler, but that is often not a concern when the vector is small and will be used only a few times, as the case might often be.