I see that the implementations of @mkitti contain the final type Array
, which is not really what I intended it to be, yet it is debatable. E.g. similar(CuArray(1:10), Float32, 5)
yields a 5-element CuArray{Float32}
and not Array{Float32}
.
I would prefer that similar(CuArray{Int64}, Float32, 5)
yields also a 5-element CuArray{Float32}
.
This could be implemented as follows:
function replace_eltype(::Type{TA}, ::Type{S}, num_dims=1) where {TA<:AbstractArray, S}
typeof(similar(TA(undef, ntuple(x->0, num_dims)), S))
end
Base.similar(::Type{A}, ::Type{S}, dims) where {T, A <: AbstractArray{T}, S} = (replace_eltype(A, S, length(dims)))(undef, dims)
but its not a very nice implementation. If there was a Metaprogramming way to access the wrapping array-type, this may be implemented in a much nicer way.
Another bad part of this implementation is, that it does not allow the user the change the number of dimensions. I.e. similar(CuArray{Int, 2, CUDA.Mem.DeviceBuffer}, Float32, 6)
yiels an error, whereas similar(CuArray{Int, 1, CUDA.Mem.DeviceBuffer}, Float32, 6)
works.
But I guess the main question is, whether it is a good idea to assume by default that arrays are mutable or whether the default should indeed (as in @mkitti 's implementation) go to the type Array
but then implementers of mutable arrays need to always care for this case individually.