# Mutiple dispatch on Tuple or "scalar"?

I want two versions of a function depending on whether the argument is a `Tuple{T,T}` or just `T`. I thought the more specific one wins, but in the code at the end of this post, the less specific `x::T` always wins over `x::Tuple{T,T}`.

My goal right now is

``````f(x = (3,5)) # -> calls f(x::Tuple{Int,Int})
f(x = 3)  # -> calls f(x::Int)
``````

How does one do this?

A more general question is, how do you have two versions, one expecting a “scalar” and the other expecting a “collection” (array, range, tuple)?

``````function f(; x::Tuple{T,T}) where {T}
print("tuple ")
print(typeof(x), " ")
@show x
end
function f(; x::T) where {T}
print("single ")
print(typeof(x), " ")
@show x
end

f(x = (3,4)) # -> single Tuple{Int64, Int64} x = (3, 4)
f(x = (3,"5")) # -> single Tuple{Int64, String} x = (3, "5")
f(x = 9) # -> single Int64 x = 9
``````

see Methods · The Julia Language. Specifically

Methods are dispatched based only on positional arguments, with keyword arguments processed after the matching method is identified.

2 Likes

… and see a related discussion at How can kwargs be used in multiple dispatch

2 Likes

Although of course you can use dispatch internally to do that:

``````julia> _f(x::T) where {T} = 1
_f (generic function with 1 method)

julia> _f(x::Tuple{T,T}) where {T} = 2
_f (generic function with 2 methods)

julia> f(;x) = _f(x)
f (generic function with 1 method)

julia> f(x=1)
1

julia> f(x=(2,3))
2
``````
3 Likes

Thank you all for your help.

Ah! That’s what I was missing!

``````f(;x) = _f(x)
``````

I see!

Out of curiosity . . . why not? Why isn’t dispatch on keyword arguments allowed? (I googled it but wasn’t able to locate a discussion for the reason.)