Setindex for CartesianIndex

The question is related to the general topic of mutating immutables.
StaticArrays comes with a helpful convenience function setindex, which allows modifying an array element at a given position and returning a new StaticArray, as far as I understand, presumably this is achieved without an additional memory allocation step.
I wonder if there something equivalent for CartesianIndex? It is a fairly common task (at least within my realm) to try and access nearest-neighbor indices.
I ended up writing the following function, which returns a CartesianIndex associated with a nearest-neighbor index, using Base.Cartesian macro.

@generated function hop(index::CartesianIndex{NDIMS},dir::Int64,lr::Int64) where {NDIMS}
    quote
       @ncall $NDIMS CartesianIndex d_t->
       begin
           if d_t==dir
             if (lr==1)
               index[d_t]+1
             else
               index[d_t]-1
             end
           else
             index[d_t]
           end
       end
    end
end

My question is whether there is a simpler “Julian” (whatever that means :slight_smile: ) approach, possibly in the spirit of StaticArray’s setindex in the context of CartesianIndex?

Snir

Perhaps we should shorten this by defining setindex on CartesianIndex, but for now

julia> I = CartesianIndex(1, 2, 3, 4, 5)
CartesianIndex(1, 2, 3, 4, 5)

julia> I = CartesianIndex(Base.setindex(Tuple(I), 50, 3))
CartesianIndex(1, 2, 50, 4, 5)
1 Like

If you want a nice syntax, you can use https://github.com/jw3126/Setfield.jl

julia> i = CartesianIndex(1, 2, 3)
CartesianIndex(1, 2, 3)

julia> j = @set i.I[2] = 200
CartesianIndex(1, 200, 3)

(If Base.setindex were implemented it’d be @set i[2] = 200)

1 Like

Adding this to base would be super nice.

Thanks! Indeed a nicer syntax.

Just opened a feature request (naturally low priority but could be nice in the future)

https://github.com/JuliaLang/julia/issues/35255#issue-587530816