Modify elements of struct without changing original inputs


I have a question regarding a situation where I want to pass a (mutable) struct to another struct.
Please see the MWE below.

mutable struct MyStruct
    arr::Array{Real, 1}

struct MyOtherStruct

function square_MyOtherStruct(mos::MyOtherStruct) =^2

my_struct = MyStruct([1, 2, 3])
my_other_struct = MyOtherStruct(my_struct)


This results in:


What I would like to achieve is to modify the ms::MyStruct element within the MyOtherStruct without changing the mystruct variable that is passed to create the MyOtherStruct.

So I would like to (still) have:


In my actual application, I want the user to still have “original” my_struct object at hand to proceed using this, while also able to perform other operations on the MyOtherStruct object that might include modifications of the contained values.

I know that this is possible by using a constructor for MyOtherStruct that makes a deepcopy of the MyStruct object before construction.

But I was wondering whether this is a recommended way of doing this or if there is a cleaner solution, especially since I read that using deepcopy is usually not a good thing and might also have some negative effects on the performance.

Either make a copy or use a non-mutable struct. Having changes visible to other references is the whole point of a mutable struct.

Even if you use a non-mutable struct, if it has a mutable member like an Array then you have to make a copy of that if you don’t want changes visible to other places that refer to the same Array. For example, if you did .=^2

(note the .=) which mutates in place rather than making a new array and re-assigning (as in your square_MyOtherStruct code above), then even if ms is non-mutable the change to arr will be visible to other places that refer to arr.

(Note also that your abstract element type in arr::Array{Real, 1} will kill performance. It’s better to use a parameterized struct type so that you can use a concretely-typed Array here.)


There are some packages which provide a convenient API to make a copy with one field modified, eg

1 Like