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

Use with mutable arrays?

Open evanfields opened this issue 4 years ago • 4 comments

If one has a mutable array of immutable objects, is it possible to use Accessors.jl to update just one object in the array without copying the whole array?

julia> struct MyT
       x::Int
       end

julia> v = [MyT(1), MyT(2)]
2-element Vector{MyT}:
 MyT(1)
 MyT(2)

julia> @set v[1].x = 5
2-element Vector{MyT}:
 MyT(5)
 MyT(2)

julia> v
2-element Vector{MyT}:
 MyT(1)
 MyT(2)

Looks like @set is returning a whole copy of v, not just updating v[1]. Is that right? Is there a way around this?

evanfields avatar Feb 27 '21 22:02 evanfields

Personally I usually do

v1 = v[1]
v[1] = @set v1.x = 5

Alternatives would be to use Persistent Arrays for efficient immutable updates of arrays. It should be easy to support FunctionalCollections with Accessors but it is not yet implemented I think. Or defining a custom lens that is allowed to do mutation. If you want to work on one of these, I am happy to help.

jw3126 avatar Feb 28 '21 05:02 jw3126

Thank you for the response and tip. Right now I'm working on some other personal projects so unfortunately it's unlikely I'll open a PR.

evanfields avatar Mar 04 '21 12:03 evanfields

Sure no problem!

jw3126 avatar Mar 04 '21 12:03 jw3126

Try the view-lens now available in AccessorsExtra:

julia> @set v |> view(_, 1)[].x = 5
2-element Vector{MyT}:
 MyT(5)
 MyT(2)

julia> v
2-element Vector{MyT}:
 MyT(5)
 MyT(2)

Suggestions for a cleaner approach that doesn't introduce new structs (for the user to learn) are welcome!

aplavin avatar Apr 23 '23 00:04 aplavin