Search code examples
arraysfunctiontemplatesjuliatype-promotion

Julia: Template functions to accept multiple array types


I'm trying to maintain code reusability whilst using the Array type, but am unsure of how to proceed without allowing "illegal" types through. Example functionality:

foo = function(x::Array{Number,2})
    print(x)
end

foo([1 2 3; 4 5 6; 7 8 9])
# 15

foo([1 2 3])
# MethodError: no method matching (::Array{Int64,1})
# Closest candidate is (::Array{Number,2})

foo(["alpha" "beta"; "pi" "rho"])
# MethodError: no method matching (::Array{String,2})
# Closest candidate is (::Array{Number,2})

However, the first example, foo([1 2 3; 4 5 6; 7 8 9]) comes back with MethodError: no method matching (::Array{Int64,2}) despite (::Array{Number,2}) theoretically being a valid promotion. I don't want to have to manually convert for every function call; nor do I want to have to declare all arrays to be of the Array{Number,2} type. I know that I could instead replace the function call with:

foo = function(x::Array)
    print(x)
end

However, this allows arrays of any dimensionality and type into the function. The only other alternative I can think of is to add boilerplate code where I initially allow any and all arrays in, check their typing and size manually, and go from there, but this feels inelegant.

Any suggestions? Thanks in advance. (Note: I am using Julia 0.6.3)


Solution

  • Use Matrix{<:Number} instead of Array{Number, 2} as type restriction and all will work (also Array{<:Number, 2} would work).

    In short Matrix{Int64} is not subtype of Matrix{Number}, but is a subtype of Matrix{T} where {T<:Number} which can be expressed as Matrix{<:Number} if you do not use T in the body of the function.

    The Julia manual here https://docs.julialang.org/en/v0.6.4/manual/types/#Parametric-Abstract-Types-1 and here https://docs.julialang.org/en/v0.6.4/manual/methods/#Parametric-Methods-1 describes in detail how subtyping in parametric types works in Julia 0.6. Then I think that you can check out this recent SO question Julia: creating a method for Any vector with missing values to understand how more complex cases of subtyping can be handled.