Using a type parameter vs abstract type in function signature

I’ve written the following function:

function all_your_base(digits::Vector{Integer}, base_in, base_out) 
    sum(digits) ≠ 0 || return([0])
    n = digits .* base_in .^ (length(digits)-1:-1:0) |> sum
    res = []
    for d ∈ base_out .^ (floor(log(base_out, n)):-1:0)
        push!(res, n ÷ d)
        n -= res[end] * d
    end
    res
end

This fails (MethodError) if I call it as follows:

all_your_base([1], 2, 10)

However it works if I rewrite my function using a type parameter:

function all_your_base(digits::Vector{T}, base_in, base_out) where {T<:Integer}
    sum(digits) ≠ 0 || return([0])
    n = digits .* base_in .^ (length(digits)-1:-1:0) |> sum
    res = []
    for d ∈ base_out .^ (floor(log(base_out, n)):-1:0)
        push!(res, n ÷ d)
        n -= res[end] * d
    end
    res
end

I don’t understand why the two behave differently. I thought these functions identical, except for the fact that using the type parameter gives me access to “T” within the body of the function.

you want Vector{<:Integer}. The term to explain why is “type invariance”.

1 Like

Or, as I understand it: Vector{Int} <: Vector{Real} is false??? · JuliaNotes.jl

2 Likes