I see this sort of code sometimes and it makes me cringe
similar(a::Array{T,1}) where {T} = Vector{T}(undef, size(a,1))
similar(a::Array{T,2}) where {T} = Matrix{T}(undef, size(a,1), size(a,2))
similar(a::Array{T,1}, S::Type) where {T} = Vector{S}(undef, size(a,1))
similar(a::Array{T,2}, S::Type) where {T} = Matrix{S}(undef, size(a,1), size(a,2))
https://github.com/JuliaLang/julia/blob/0ea61fa153c69e052097f1307dafbedd00049aae/base/array.jl#L373
Because we already have this
similar(a::AbstractArray{T}) where {T} = similar(a, T)
similar(a::AbstractArray, ::Type{T}) where {T} = similar(a, T, to_shape(axes(a)))
similar(a::AbstractArray{T}, dims::Tuple) where {T} = similar(a, T, to_shape(dims))
similar(a::AbstractArray{T}, dims::DimOrInd...) where {T} = similar(a, T, to_shape(dims))
similar(a::AbstractArray, ::Type{T}, dims::DimOrInd...) where {T} = similar(a, T, to_shape(dims))
https://github.com/JuliaLang/julia/blob/0ea61fa153c69e052097f1307dafbedd00049aae/base/abstractarray.jl#L781
I believe that in this case it is written to special case low low numbers of arguments to avoid packing and unpacking into an NTuple
, but I’m not sure. Is this necessary for maximum performance? Is it possible to delegate those special casings to the compiler whenever the NTuple
’s N
is known at compile time (almost always)? Does the compiler already do this?