我有一个函数,返回一个与输入数组相同的元素类型的数组,但是有一个额外的维度。 这是一个简单的例子:
function myfun(a::Array{T,N}) where {T,N}
b = Array{T,N+1}(size(a)...,2)
b[:] = 42
return b
end
在2x2阵列上调用此函数时,它返回一个2x2x2数组。
myfun(zeros(2,2))
2×2×2 Array{Float64,3}:
[:, :, 1] =
42.0 42.0
42.0 42.0
[:, :, 2] =
42.0 42.0
42.0 42.0
但是,此功能不是类型稳定的。根据{{1}},@code_warntype
的类型为b
。
即使在Any
上使用了类型注释,结果也不是类型稳定的
关于维度的数量:
b
function myfun(a::Array{T,N}) where {T,N}
b = Array{T,N+1}(size(a)...,2) :: Array{T,N+1}
b[:] = T(42)
return b
end
现在返回@code_warntype myfun(zeros(2,2))
类型Array{Float64,_} where _
。当输入参数有2个维度时,Julia是否应该无法确定维数为3?
我正在使用julia 0.6.2(在linux上)。
答案 0 :(得分:3)
由于构造函数(Array{T,N+1}(size(a)...,2)
)在运行时执行,您可以在编译时使用@generated functions预先计算N
:
julia> @generated function myfun(a::Array{T,N}) where {T,N}
NN = N+1
quote
b = Array{$T,$NN}(size(a)...,2)
b[:] = 42
return b
end
end
myfun (generic function with 1 method)
julia> @code_warntype myfun(zeros(2,2))
Variables:
#self# <optimized out>
a::Array{Float64,2}
b::Array{Float64,3}
Body:
begin # line 2:
# meta: location REPL[1] # line 4:
SSAValue(2) = (Base.arraysize)(a::Array{Float64,2}, 1)::Int64
SSAValue(1) = (Base.arraysize)(a::Array{Float64,2}, 2)::Int64
b::Array{Float64,3} = $(Expr(:foreigncall, :(:jl_alloc_array_3d), Array{Float64,3}, svec(Any, Int64, Int64, Int64), Array{Float64,3}, 0, SSAValue(2), 0, SSAValue(1), 0, :($(QuoteNode(2))), 0)) # line 5:
$(Expr(:invoke, MethodInstance for fill!(::Array{Float64,3}, ::Int64), :(Base.fill!), :(b), 42))
# meta: pop location
return b::Array{Float64,3}
end::Array{Float64,3}
julia> myfun(zeros(2,2))
2×2×2 Array{Float64,3}:
[:, :, 1] =
42.0 42.0
42.0 42.0
[:, :, 2] =
42.0 42.0
42.0 42.0