5
votes

In Julia, I can use promote to make various types of objects compatible. For example:

>promote(1, 1.0)
(1.0,1.0)
>typeof(promote(1, 1.0))
(Float64, Float64)

However, if I use promote on arrays, it doesn't give me what I want:

>promote([1], [1.0])
([1],[1.0])
>typeof(promote([1], [1.0]))
(Array{Int64,1},Array{Float64,1})

What I want is for the Int64 array to be converted to a Float64 array, so I get something like:

>promote_array([1], [1.0])
([1.0],[1.0])
>typeof(promote_array([1], [1.0]))
(Array{Float64,1},Array{Float64,1})

Here promote_array is a hypothetical function I made up. I'm looking for a real function that does the same. Is there a function in Julia that does what promote_array does above?

2

2 Answers

4
votes

I found the function Base.promote_eltype, which I can use to get what I want:

function promote_array(arrays...)
  eltype = Base.promote_eltype(arrays...)
  tuple([convert(Array{eltype}, array) for array in arrays]...)
end

This promote_array function then gives me the output I'm looking for:

>promote_array([1], [1.0])
([1.0],[1.0])
>typeof(promote_array([1], [1.0]))
(Array{Float64,1},Array{Float64,1})

The above solves my problem, although the existence of Base.promote_eltype suggests there may be an already built solution that I don't know about yet.

4
votes

Here is what I would do:

function promote_array{S,T}(x::Vector{S},y::Vector{T})
    U = promote_type(S,T)
    convert(Vector{U},x), convert(Vector{U},y)
end

I'm not sure what your use case is exactly, but the following pattern is something I see as being fairly commonly required for code that has the tightest typing possible while being general:

function foo{S<:Real, T<:Real}(x::Vector{S},y::Vector{T})
    length(x) != length(y) && error("Length mismatch")
    result = zeros(promote_type(S,T), length(x))
    for i in 1:length(x)
        # Do some fancy foo-work here
        result[i] = x[i] + y[i]
    end
    return result
end