Unable to construct `Union` of `Vararg`

When I tried to construct Union of Vararg like

julia> Union{Vararg{Any, 1}, Vararg{Any, 2}}

I got

ERROR: TypeError: in Union, expected Type, got Vararg{Any, 1}

but clearly

julia> Vararg{Any, 1} isa Type
true

julia> [Vararg{Any, 1}, Vararg{Any, 2}] isa Array{<:Type, 1}
true

Is this intended behavior and I’m missing something here? Thank you!

Vararg shouldn’t be a Type this is a bug in previous Julia versions and has been fixed in Julia 1.7, See also: Vararg subtyping is inconsistent between 1.0 and 1.6 · Issue #40405 · JuliaLang/julia · GitHub


not sure if this can be backported to 1.6 if 1.6 is gonna be LTS tho, @kristoffer.carlsson probably knows

4 Likes

Thank you, Roger! Then if I want to realize a similar goal here, do you know there’s a way to do that? Specifically, I want to control the allowed N in Vararg{T, N} as the type of the argument type for a function in an efficient way. For example, only allow the number of arguments to be 1,2,3,4.

I know I can at least do it by:

foo(a1=nothing, a2=nothing, a3=nothing, a4=nothing) = []

Thank you!

note, Vararg means less than N arguments, thus it doesn’t make sense to have Union{Vararg{Any, 1}, Vararg{Any, 2}} either

julia> foo(xs::Vararg{Int, 4}) = xs
foo (generic function with 1 method)

julia> foo(1,2,3,4)
(1, 2, 3, 4)

julia> foo(1,2,3,4, 5)
ERROR: MethodError: no method matching foo(::Int64, ::Int64, ::Int64, ::Int64, ::Int64)
Closest candidates are:
  foo(::Int64, ::Int64, ::Int64, ::Int64) at REPL[1]:1
Stacktrace:
 [1] top-level scope
   @ REPL[3]:100: 

I think Vararg{T, 4} means “exactly N type-T arguments”?

julia> foo(xs::Vararg{Int, 4}) = xs
foo (generic function with 1 method)

julia> foo(1,2,3,4)
(1, 2, 3, 4)

julia> foo(1,2,3)
ERROR: MethodError: no method matching foo(::Int64, ::Int64, ::Int64)
1 Like

oh yeah, you are right, that’s exactly N arguments.

then you can do the following

julia> for N in [1, 4]
           @eval foo(xs::Vararg{Int, $N}) = xs
       end

julia> foo(1)
(1,)

julia> foo(2)
(2,)

julia> foo(2, 3)
ERROR: MethodError: no method matching foo(::Int64, ::Int64)
Closest candidates are:
  foo(::Int64, ::Int64, ::Int64, ::Int64) at REPL[8]:2
  foo(::Int64) at REPL[8]:2
Stacktrace:
 [1] top-level scope
   @ REPL[11]:1

This seems like an alternative solution. Thank you!