Unpack types in Union

Sorry if I missed someone suggesting this somewhere, but this thread seemed to be mostly concerned with telling the OP to do something else. In case the OP or someone else actually does just need a function that turns a regular Union into a list of the union members, one way to do it without relying on internals would be like so:

function usplit(::Type{T}, acc=()) where {T}
    if T isa Union
        U, V = _usplit(T)
        (usplit(U)..., usplit(V)..., acc...)
    else
        (T, acc...)
    end
end
_usplit(::Type{Union{T, U}}) where {T, U} = (T, U)

then you can do e.g.

julia> usplit(Union{Int, String, Array})
(Int64, String, Array)

This sort of thing should be efficiently hoisted to compile time whenever the union is statically known.

I chose to return a Tuple here because it has nice static properties, but if you need an Array you could just collect it at the end.

2 Likes

@Mason as discussed in the linked issue, your implementation is not correct, according to vtjnash.

relies upon an implementation bug in subtyping and should be avoided in real code

I suppose one reason for that is that is that the semantics of what gets matched as T, and what gets matched as U, are not well defined.

For example, should _usplit(Union{Int, Float32}) return (Int, Float32) or should it return (Float32, Int)? What about more complex types?

2 Likes

I see, that’s unfortunate. I’m not sure why it would be so bad if the order was the only issue, but with such a laconic statement like the one from from the linked issue, it’s hard to know if that’s the only potential problem.

1 Like