Difference between vector and vector of vectors

My function f(x::Vector) works on a vector of numbers (e.g. x=[0.1, 0.2]).

However, I’d like to create another method for vector of vectors (e.g. x=[[0.1, 0.2], [0.3, 0.4]]), which uses the vector-of-numbers version.

However, it seems that x=[0.1, 0.2] and x=[[0.1, 0.2], [0.3, 0.4]] are of the same type: the vector-of-vectors is caught and processed by the first version.

How can I specify vector-of-vectors and vector-of-numbers as types to dispatch on? Thank you!

I’d recommend using broadcasting in this case: that’s just f.([[0.1, 0.2], [0.3, 0.4]]). Broadcasting works element-wise across the container you pass it, without needing to define an additional method.

A vector of vectors is indeed just a vector. The difference is in its element type:

f(x::Vector{<:Number}) = "vector of numbers"
f(x::Vector{<:Vector}) = "vector of vectors"
julia> f([1,2,3])
"vector of numbers"

julia> f([[1,2],[3,4]])
"vector of vectors"

But note that this isn’t the same as saying what they contain — it’s just a property of the vector itself. In fact, you can have vectors that contain just numbers and won’t work with the above, because they can contain Anything:

julia> f(Any[1,2,3])
ERROR: MethodError: no method matching f(::Array{Any,1})
Closest candidates are:
  f(::Array{#s1,1} where #s1<:Real) at REPL[10]:1
  f(::Array{#s1,1} where #s1<:(Array{T,1} where T)) at REPL[10]:2
 [1] top-level scope at none:0

Awesome, thanks for that comprehensive reply!

I would just add a change to the type notation as my preferred one,
if you wanted to allow a more flexible approach which I don’t particularly recommend,

f(obj::AbstractVector) = all(elem isa Number for elem ∈ obj) ?
                         f(convert(Vector{reduce(promote_type, typeof(elem) for elem ∈ obj)}, obj)) :
                         throw(ArgumentError("elements should all be numbers"))
f(::AbstractVector{<:Number}) = ...

I would just keep the second one.