# Getting this type signature correct

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.