Julia: Unintuitive dispatch due to empty tuple/varargs specificity

Created on 24 Oct 2017  路  7Comments  路  Source: JuliaLang/julia

julia> f(::Int...) = 1
f (generic function with 1 method)

julia> f(::Any...) = 2
f (generic function with 2 methods)

julia> f()
1

This doesn't necessarily seem incorrect, but naively, I would've expected an ambiguity error here. I find it unintuitive that Tuple{} is somehow "closer" to Tuple{Vararg{Int}} than Tuple{Vararg{Any}} wrt dispatch specificity. It's arguable that the reverse would actually be more useful (though it still seems like an ambiguity error would be more correct).

EDIT: made some changes to make my point clearer - I wasn't trying to imply that the current behavior is incorrect

doc types and dispatch

Most helpful comment

Everything that matches the first one would also match the second one so the first one is strictly more specific than the second one and this seems correct?

All 7 comments

Everything that matches the first one would also match the second one so the first one is strictly more specific than the second one and this seems correct?

@yuyichao is right, and I'll also note that we lack the ability to resolve ambiguity relative to specific actual arguments --- i.e. these definitions are arguably ambiguous for 0 arguments, but the first one is clearly more specific if there are more arguments. I believe changing that would be fairly complex.

this seems correct?

Right, hence my comment that the example wasn't necessarily incorrect, just that I would've preferred an ambiguity error if possible 馃槢

we lack the ability to resolve ambiguity relative to specific actual arguments...I believe changing that would be fairly complex.

Fair enough, I doubt this comes up often enough to justify "fixing" it. Might be worth adding a note to the "avoiding ambiguities" docs section, though.

Seems so.

I think it's good to add rules that makes intersecting signatures that are not subsets of each other unambiguous, but adding rules to make a subset ambiguous is a little wierd......

With another argument this can seem even more "unintuitive":

julia> f(::Any, ::Int...) = 1
f (generic function with 1 method)

julia> f(::Type{Int}, ::Any...) = 2
f (generic function with 2 methods)

julia> f(Int)
ERROR: MethodError: f(::Type{Int64}) is ambiguous. Candidates:
  f(::Type{Int64}, ...) in Main at REPL[2]:1
  f(::Any, ::Int64...) in Main at REPL[1]:1
Possible fix, define
  f(::Type{Int64}, ::Vararg{Int64,N} where N)

In this example there seems to be a bug depending on the order of calls:

julia> f(::Any, ::Int...) = 1
f (generic function with 1 method)

julia> f(::Type{Int}, ::Any...) = 2
f (generic function with 2 methods)

julia> f(UInt)
1

julia> f(Int) # no more ambiguity, but not the result I expected
1

dup #17377, and the issue in the previous comment appears to be fixed now

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wilburtownsend picture wilburtownsend  路  3Comments

i-apellaniz picture i-apellaniz  路  3Comments

Keno picture Keno  路  3Comments

manor picture manor  路  3Comments

arshpreetsingh picture arshpreetsingh  路  3Comments