f(x::Tuple{Any, Any}) = "Tuple{Any, Any}"
f(x::NTuple{N}) where N = "NTuple{N}"
When I write f((1,2)) the call satisfies both definitions. On Julia 0.6 the second definition is called but I do not understand why. Is this a bug or there is some explanation for this behavior?
I would assume that MethodError should be thrown as this call is ambiguous because:
julia> typeof((1,2)) <: Tuple{Any, Any}
true
julia> typeof((1,2)) <: NTuple{N} where N
true
but
julia> Tuple{Any, Any} <: NTuple{N} where N
false
julia> (NTuple{N} where N) <: Tuple{Any, Any}
false
NTuple requires that all the inputs have the same type, so
julia> typeof((1,2)) <: NTuple{N} where N
true
julia> typeof((1,2.0)) <: NTuple{N} where N
false
Hence it is deemed “more specific,” as the lingo goes, and hence gets priority.
Of course this can be debated: why should the element type receive priority over the length? If you need to have manual control over this, you can always define a method for ::NTuple{2} and have it do whichever one you want.
Thank you. Now I understand that it is governed by jl_type_morespecific.
As a side observation: for Array dimension gets the priority over element type as Array{T, 1} where T is more specific than Array{Int, N} where N (so I would say it is the other way around than in Tuple although there is no one to one correspondence between those cases).