Here is a demonstration of some behavior of the Julia typesystem.
function mine(x::Vector{Union{Int64, T}}) where T
println(typeof(x))
println(T)
end
julia> mine(Vector{Union{Int64, String}}([1, 2, 3, "hello"]))
Vector{Union{Int64, String}}
String
julia> mine(([1, 2, 3, "hello"]))
Vector{Any}
Any
In the second case, the type is not Vector{Union{Int64, String}}. It is also not Vector{Union{Int64, Any}} which might be a sensible next guess for something more general.
Instead, the type is Vector{Any}.
I have noticed that Vectors (and presumably other types as well) tend to like to default to T=Any, unless their arguments match on the type exactly.
To re-phrase the question another way, it seems the core thing to notice here is that the expression [1, 2, 3, "hello"] produces a Vector{Any}.
- Q1: Is that by design?
- Q2: Is there a particular reason for this?
The alternative would be for this to evaluate to Vector{Union{Int64, String}}.
I think I am correct in stating that if it were the latter, then this would be advantageous for the multiple-dispatch system, for two reasons:
- Precision.
T=Union{Int64, String}more precisely defines what is contained within the vector. By contrast,T=Anyis a less precise statement about what is contained within the vector. It is a more accurate, or correct, statement about what the vector contains. If you were asked in a court of law, this would be a better thing to say. - Specificity. (Meaning less general.) If two functions are defined which take arguments of type
Vector{Union{Int64, String}}andVector{Any}, then we have lost the ability to dispatch on the more specific version. (Which is forT=Union{Int64, String}.
One final thing to note. I believe I am correct in thinking that Vector{Any} is not a supertype of Vector{Union{Int64, String}} despite the fact that Any is a supertype of Union{Int64, String}. This is because the types must be organized into a tree structure, which does not have enough flexibility to fully describe whether one type is compatible with another rather than just being a subtype of another.
Also note that Any is a supertype of Vector{<anything>}, but the Julia type system stops at the level of Vector{Any}. It doesn’t “promote” this type all the way to Any. (Is it obvious what I mean here?)
Any <: Vector{Any} <: Vector{Union{...}}
Please do correct me if I am wrong about this.