I disagree. Actually, Julia can produce highly efficient code in some circumstances, even in the presence of large unions. For example, in the following code:
julia> struct Foo
x::Union{Int, UInt, Int8, UInt8, Int16, UInt16, Int32, UInt32}
end
julia> function foo(x::Foo)
xx = x.x
if xx isa Int
return 0
elseif xx isa UInt
return 1
elseif xx isa UInt8
return 2
elseif xx isa UInt16
return 3
elseif xx isa UInt32
return 4
elseif xx isa Int8
return 5
elseif xx isa Int16
return 6
elseif xx isa Int32
return 7
end
end
foo (generic function with 1 method)
julia> foo(Foo(1))
Here, Julia is able to correctly infer that xx
is a large union, and to eliminate each of the union’s members one by one in the if statement. It correctly infers a return type of Int
(as opposed to Union{Int, Nothing}
, indicating it statically knows all the possible types are covered), and it compiles the function to use a lookup table to get the type.
The problem is that Julia’s semantics don’t provide any kind of mechanism to handle unions effectively. All we can do now is hope that Julia is able to do union-splitting, but the precise circumstances where this occurs is subject to change (and effectively unknowable from the outside). In my example above, for example, there are way more types than the MAX_TYPEUNION_*
parameters in Julia, yet it still works well.
In contrast, if Julia provided, say, some kind of match statement which could be applied to a Union-typed struct field, it would be able to give guarantees that no dynamic dispatch happened. Note that this is a much simpler thing than to handle arbitrary large unions in inference - what I demonstrate here (and what OP asks for) is essentially just a fancy if-statement applied to unions.
Of course one could argue that we already have unions and if-statements, so what’s the problem? Well:
- Even though it works right now, it’s hard to know whether it’s supposed to be efficient, or whether Julia can just give up and emit bad code
- It would be nice to have a statement that statically checked all the union variants were covered. That would only work with fields from structs, though, so unless we have something like SumTypes.jl, it’ll be of limited utility