Создание функции с параметрическим типом возврата

#julia

Вопрос:

У меня есть ситуация, когда я хотел бы задать функцию с параметрическим типом возврата — упрощенный пример ниже. Похоже, что в настоящее время это невозможно — какую логическую идиому использовать вместо этого? Для меня не очевидно, как добиться разумного повторного использования кода.

 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)
 

Любые мысли оценены по достоинству.

Ответ №1:

Как вы, возможно, заметили , параметрически определенные функции, например, такие функции foo{T}(x) , могут быть определены только в том случае, если они являются конструкторами для типа (который уже определен). Вместо этого вы можете взять желаемый тип вывода в качестве аргумента функции, например:

 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)
 

Обратите внимание, что литерал 1 уже является целым числом. Нет необходимости писать 1::Int64 .

Также обратите внимание на использование одноэлементного типа в сигнатуре функции. Это служит только для ограничения отправки. Вы могли бы написать get_output так, и это сработало бы нормально:

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

Кстати, я бы настоятельно не рекомендовал этого делать, но можно обмануть, так как компилятор Julia не гарантирует, что конструкторы на самом деле возвращают экземпляры типов, которые они должны создавать:

 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)
 

Комментарии:

1. Спасибо — это отлично работает. Интересно работать с языком, в котором типы являются гражданами первого класса-это кажется очень классной функцией.