Should setindex(x::AbstractArray, v, i) use mutate-or-widen strategy?
Current implementation of setindex(x::AbstractArray, v, i) does not support widening of the element type:
https://github.com/JuliaDiffEq/ArrayInterface.jl/blob/c8513cbc0b9dc24e6674206255838abec553b854/src/ArrayInterface.jl#L22-L26
I think it would be useful to support eltype-widening so that setindex([0], 1.2, 1) works. I implemented this in BangBang.jl internally (BangBang.jl provides a uniform API for mutable and immutable containers). It is useful to have type-changing setter because you can use it to, e.g., implement map based on mutate-or-widen strategy.
Actual code is pretty simple (from https://github.com/tkf/BangBang.jl/blob/94eab8d728194fac0fa41c840ca398600a50f903/src/NoBang/base.jl#L99-L107):
function _setindex(xs::AbstractArray, v, I...)
T = promote_type(eltype(xs), typeof(v))
ys = similar(xs, T)
if eltype(xs) !== Union{}
copy!(ys, xs)
end
ys[I...] = v
return ys
end
One disadvantage of this approach is that it fails when there is an undef element. That's why Union{} was special-cased above. To support more general cases, I think we need something like copy_if_defined! (or maybe Base.copy! should do it automatically?).
I am not sure we want to change the element type? I would assume it would have array-like semantics.
But what is an array-like semantics? I think we still can define semantics for corner cases?
The type-widening API is more-or-less [1] a strict superset of the non-type-changing API because the type-widening API turns error cases in non-type-changing API to valid cases. The type-widening immutable API is a useful building block for the mutate-or-widen strategy. Sometimes you need it for writing generic algorithm without relying on the inference API.
[1] There is a change in how setindex([0], 1.0, 1) works. In non-type-changing API it returns [1] while in type-widening API it returns [1.0].
I guess yes it makes sense on static arrays so it probably makes sense here.