Julia 切分元组时避免类型不稳定
这个问题是JuliaLang Zulip帮助热线中出现的问题的改编版本Julia 切分元组时避免类型不稳定,julia,Julia,这个问题是JuliaLang Zulip帮助热线中出现的问题的改编版本 假设我有一个函数,它接受一个异构类型的元组,并将返回该元组的一个切片,其中切片索引可以仅从类型信息静态推断。如何以正确推断输出类型的方式编写函数 例如,假设我的函数是 function f(t::Tuple, A::Array{T, N}) where {T, N} if T <: AbstractFloat imin = 1 elseif T <: Integer
假设我有一个函数,它接受一个异构类型的
元组
,并将返回该元组的一个切片,其中切片索引可以仅从类型信息静态推断。如何以正确推断输出类型的方式编写函数
例如,假设我的函数是
function f(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
t[imin:imax]
end
如何编写
f
使其工作?我最喜欢的策略(但可能有更简单的方法?)是编写@生成的
函数,以手动确保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
瞧,推断出的输出类型是长度为3的
元组
,其元素静态地称为字符串
,以及Int
和Float64
您必须调用一些未报告的函数,但是您可以在不使用生成的@函数的情况下调用这些函数,例如:
julia> function f(t::Tuple, A::Array{T, N}) where {T, N}
t = Base.IteratorsMD.split(t, Val(N+2))[1]
if !(T<:AbstractFloat)
t = Base.tail(t)
if !(T<:Integer)
t = Base.tail(t)
end
end
return t
end
f (generic function with 1 method)
julia> let t = (:a, "b", 2, 3.0, Val(1), 2+im), A = rand(Int, 3,3)
Base.return_types(f, Tuple{typeof(t), typeof(A)})
end
1-element Array{Any,1}:
Tuple{String,Int64,Float64}
julia>函数f(t::Tuple,A::Array{t,N}),其中{t,N}
t=Base.IteratorsMD.split(t,Val(N+2))[1]
如果!(T
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}
julia> function f(t::Tuple, A::Array{T, N}) where {T, N}
t = Base.IteratorsMD.split(t, Val(N+2))[1]
if !(T<:AbstractFloat)
t = Base.tail(t)
if !(T<:Integer)
t = Base.tail(t)
end
end
return t
end
f (generic function with 1 method)
julia> let t = (:a, "b", 2, 3.0, Val(1), 2+im), A = rand(Int, 3,3)
Base.return_types(f, Tuple{typeof(t), typeof(A)})
end
1-element Array{Any,1}:
Tuple{String,Int64,Float64}