Unexpected multiple dispatch behaviour


#1

Hello,

I define the following two methods:

u = [[1,1,1,1], [5,5]]

f(u::Vector{<:Number}) = println("here!")
f(u::Vector{Vector{<:Number}}) = println("there!")

Dispatching f() on a vector of numbers works.

f(u[1])
here!

Dispatching on a vector of vectors of numbers does not

f(u)
MethodError: no method matching f(::Array{Array{Int64,1},1})
Closest candidates are:
  f(!Matched::Array{Array{#s1,1} where #s1<:Number,1})
  f(!Matched::Array{#s1,1} where #s1<:Number)

although

Int64 <: Number
true

I went through the manual but the above behaviour remains unclear.

Thanks in advance.
Jan


#2

You want

u = [[1,1,1,1], [5,5]]

f(u::Vector{<:Number}) = println("here!")
f(u::Vector{<:Vector{<:Number}}) = println("there!")

It’s because of the way <: is lowered, it just “wraps” around one set of brackets.


#3

Thanks a lot. I think I understand now.

Best Regards,
Jan


#4

I thought f(u::Vector{Vector{<:Number}}) would be short-form notation for f(u::Vector{Vector{T}}) where {T<:Number}.
The latter long-form notation works as expected.
Could this be considered a bug in the way the short-form is lowered?


#5

It was a conscious decision by @stevengj. Vector{Vector{<:Number}} is equivalent to Vector{Vector{T} where T<:Number}. The rationale is probably somewhere in:

https://github.com/JuliaLang/julia/pull/20414
https://github.com/JuliaLang/julia/issues/6984


#6

It’s also the reason I don’t like this syntax for nested types (I’m sure people will get confused). Ref https://github.com/JuliaLang/julia/issues/6984#issuecomment-277067068


#7

Ah I think I get it now.
The placement of where can be a bit tricky.
Thanks for clarifying.