Chris J Harris
Chris J Harris

Reputation: 1851

Creating a function with a parametric return type

I have a situation where I'd like to set a function with a parametric return type - a simplified example below. It seems like this is not currently possible - what is the logical idiom to use instead? It is not obvious to me how to achieve reasonable code re-use.

struct Output{T <: Number}
    other_details::String # lots of stuff here
    numeric_output::T
end

function get_output{T <: Number}(input)::Output{T}
    transformed_input = input
    # Do stuff to transformed_input
    Output{T}(
        "lots of data",
        transformed_input
    )
end

input = 1::Int64
get_output{Float64}(input)

Any thoughts appreciated.

Upvotes: 3

Views: 216

Answers (1)

Cameron Bieganek
Cameron Bieganek

Reputation: 7704

As you might have noticed, parametrically defined functions, e.g. functions like foo{T}(x), can only be defined if they are constructors for a type (which has already been defined). What you can do instead is take the desired output type as a function argument, like this:

struct Output{T <: Number}
    other_details::String
    numeric_output::T
end

function get_output(::Type{T}, input) where {T <: Number}
    Output("lots of data", T(input))
end
julia> get_output(Float64, 1)
Output{Float64}("lots of data", 1.0)

Note that a literal 1 is already an integer. There's no need to write 1::Int64.

Also note the use of a singleton type in the function signature. This only serves to restrict the dispatch. You could write get_output like this and it would work fine:

get_output(T, input) = Output("lots of data", T(input))

By the way, I would strongly recommend against doing this, but it is possible to cheat, since the Julia compiler does not enforce that constructors actually return instances of the types that they are supposed to construct:

struct Output{T <: Number}
    other_details::String
    numeric_output::T
end

struct get_output{T} end

function get_output{T}(input) where {T <: Number}
    Output("lots of data", T(input))
end
julia> get_output{Float64}(1)
Output{Float64}("lots of data", 1.0)

Upvotes: 5

Related Questions