Say I have a function that accepts at least one argument of Union{Int, Colon, OrdinalRange}
. I can write this like:
function test(i::Union{Int, Colon, OrdinalRange}, I::Union{Int, Colon, OrdinalRange}...)
println((i, I...))
end
But that’s a tad verbose. I could obviously create a typedef for the Union, but let’s say this is a one-off function and I’d rather avoid polluting my namespace. So I tried:
function test(I::P, I::P...) where P <: Union{Int, Colon, OrdinalRange}
println((i, I...))
end
However, this fails with MethodError
when called with 2 arguments. For example, if I call test(1, 2)
, this correctly matches on the first argument, but not on the second argument.
Why is this?
When I use your second definition, test(1, 2)
works for me, but test(1, :)
does not:
julia> function test(i::P, I::P...) where P <: Union{Int, Colon, OrdinalRange}
println((i, I...))
end
test (generic function with 1 method)
julia> test(1, 2)
(1, 2)
julia> test(1, :)
ERROR: MethodError: no method matching test(::Int64, ::Colon)
Closest candidates are:
test(::P, ::P...) where P<:Union{Colon, Int64, OrdinalRange} at REPL[2]:1
The reason is because the second definition declares that all the arguments are of the same type P
. So your second definition is not equivalent to the first definition, because in your first definition the arguments can be of different types.
1 Like
Duh. Yes, of course! Thanks for that @CameronBieganek!
1 Like
By the way, you can use a let
block if you want to have a local type alias that doesn’t pollute your namespace:
julia> let
T = Union{Int, Colon, OrdinalRange}
global foo(x::T, y::T...) = (x, y)
end
foo (generic function with 1 method)
julia> foo(1, :)
(1, (Colon(),))
julia> T
ERROR: UndefVarError: T not defined
Though in this case I would probably just write it out the long way.