Types 函数向输入参数添加维度时的类型稳定性问题

Types 函数向输入参数添加维度时的类型稳定性问题,types,julia,generic-programming,Types,Julia,Generic Programming,我有一个函数,它返回的数组的元素类型与输入数组相同,但有一个额外的维度。 下面是一个简单的例子: function myfun(a::Array{T,N}) where {T,N} b = Array{T,N+1}(size(a)...,2) b[:] = 42 return b end 在2x2数组上调用此函数时,它将返回2x2数组 myfun(zeros(2,2)) 2×2×2 Array{Float64,3}: [:, :, 1] = 42.0 42.0 42.0

我有一个函数,它返回的数组的元素类型与输入数组相同,但有一个额外的维度。 下面是一个简单的例子:

function myfun(a::Array{T,N}) where {T,N}
   b = Array{T,N+1}(size(a)...,2)
   b[:] = 42
   return b
end
在2x2数组上调用此函数时,它将返回2x2数组

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
但是,此函数的类型不稳定。根据
@code\u 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\u warntype myfun(零(2,2))
现在返回
b
类型的数组{Float64,{u},其中。当输入参数有两个维度时,Julia是否应该不能计算出维度数是3


我使用的是julia 0.6.2(在linux上)。

这是因为构造函数(
数组{T,N+1}(大小(a)…,2)
)是在运行时执行的,您可以使用它在编译时预计算
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
julia>@生成函数myfun(a::数组{T,N}),其中{T,N}
NN=N+1
引用
b=数组{$T,$NN}(大小(a)…,2)
b[:]=42
返回b
结束
结束
myfun(具有1个方法的通用函数)
julia>@code_warntype myfun(零(2,2))
变量:
#自我#
a::数组{Float64,2}
b::数组{Float64,3}
正文:
开始#第2行:
#meta:location REPL[1]#第4行:
SSAValue(2)=(Base.arraysize)(a::数组{Float64,2},1)::Int64
SSAValue(1)=(Base.arraysize)(a::数组{Float64,2},2)::Int64
数组{Float64,3}=$(Expr(:foreigncall,:(:jl_alloc_Array_3d),数组{Float64,3},svec(Any,Int64,Int64,Int64,Int64),数组{Float64,3},0,SSAValue(2),0,SSAValue(1),0,:($(QuoteNode(2)),0))#第5行:
$(Expr(:invoke,MethodInstance for fill!(::数组{Float64,3},::Int64),:(Base.fill!),:(b),42))
#梅塔:流行位置
返回b::数组{Float64,3}
结束::数组{Float64,3}
julia>myfun(零(2,2))
2×2×2数组{Float64,3}:
[:, :, 1] =
42.0  42.0
42.0  42.0
[:, :, 2] =
42.0  42.0
42.0  42.0