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.

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:

#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.