ArrayInterface.jl icon indicating copy to clipboard operation
ArrayInterface.jl copied to clipboard

Should setindex(x::AbstractArray, v, i) use mutate-or-widen strategy?

Open tkf opened this issue 6 years ago • 3 comments

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?).

tkf avatar Jul 31 '19 02:07 tkf

I am not sure we want to change the element type? I would assume it would have array-like semantics.

ChrisRackauckas avatar Jul 31 '19 10:07 ChrisRackauckas

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].

tkf avatar Jul 31 '19 22:07 tkf

I guess yes it makes sense on static arrays so it probably makes sense here.

ChrisRackauckas avatar Aug 01 '19 19:08 ChrisRackauckas