Стратегия, с которой мне было бы удобнее (но, может быть, есть более простой способ?), Состоит в том, чтобы написать функцию @generated
, чтобы вручную убедиться, что julia выполняет операции уровня типа, которые я хочу во время компиляции:
@generated function f2(t::Tuple, A::Array{T, N}) where {T, N}
if T <: AbstractFloat
imin = 1
elseif T <: Integer
imin = 2
else
imin = 3
end
imax = N+2
out_expr = Expr(:tuple, (:(t[$i]) for i ∈ imin:imax)...)
end
Идея заключается в том, что в сгенерированном теле функции во время компиляции мы определяем, что такое imin
и imax
, а затем вручную строим выражение для нашего тела функции, которое читает (t[imin], t[imin+1], ..., t[imax-1], t[imax])
.
По любым причинам, Джулия может лучше рассуждать о последовательности getindex(::Tuple, ::Int)
, чем о нарезке кортежа, даже со статически известным слайсом, поэтому, вручную создавая это выражение, компилятор может сделайте то, что мы хотим:
julia> let t = (:a, "b", 2, 3.0, Val(1), 2+im), A = rand(Int, 3,3)
Base.return_types(f2, Tuple{typeof(t), typeof(A)})
end
1-element Array{Any,1}:
Tuple{String,Int64,Float64}
Вуаля, выводимый тип вывода - это Tuple
длины 3, чьи элементы статически известны как String
, Int
и Float64
!