Confused about parametric method definitions


#1

As a beginner programmer who’s relatively new to Julia, I’m a bit confused about how method definitions work. If I define a simple function as follows:

function xy{T<:Real}(x::Vector{T}, y::Vector{T})
    out = x .* y
end

Why do I get a MethodError if, for example, x is of type Int64 and y is of type Float64? There’s a similar example in the Methods documentation, but it’s still not clear to me why both types can’t be used in the function if they are both subtypes of Real. This may stem from my misunderstanding of how type parameters are used in the method signature.

I often work with data that can be of various types and it would be rather cumbersome to convert them all to similar types prior to executing a function. For example, the function above wouldn’t work if x was of type Float32 and y was of type Float64. A trivial solution would be a more generalized form of the function:

function xy(x::Vector, y::Vector)
    out = x .* y
end

However, I feel that this isn’t ideal. If I wanted to add a two-dimensional array to the parameter tuple, I’m not sure how I would explicitly enforce the dimensionality of the array without the presence of a method type parameter T. For example, a function with definition as follows:

function xyz{T<:Real}(x::Vector{T}, y::Vector{T}, z::Array{T,2})

would require z to be a 2-dimensional array, but also require it have the same type as x and y.

I was hoping someone could provide me with some clarity on the technical aspects involved with this. And more importantly, what is the recommended “Julian” way of proceeding if x, y, and z are of different types?


#2

What you wrote there is “both must be vectors of type T, where T must be some Real number”. That’s different then

function xy{T<:Real,T2<:Real}(x::Vector{T}, y::Vector{T2})
    out = x .* y
end

Also note the shorthand

function xy(x::Vector{<:Real}, y::Vector{<:Real})
    out = x .* y
end

for v0.6.

You can always do ndims(x), or use typeof(x) or eltype(x) in the function.

In this sense, why would you restrict to Vector and Array instead of AbstractVector and AbstractArray? I cannot think of many examples which actually need a standard array (those that do, it’s because they are calling C).


#3

Ok, this makes more sense. I guess I wasn’t properly following the logic here.

This looks like a much better alternative to all the previous solutions. Thanks for the help!