 # Confused by pass-by-sharing

In the following simple stylised script,

``````mutable struct P <: AbstractP
this
that
end

p = P()
...
sol1 = optimal(p)
q = p
p = add(p, something)  # p changed
sol2 = optimal(p)
p = q
sol3 = optimal(p)
``````

would like that sol3 = sol1, but instead got sol3 = sol2. Unfortunatelly, it is still not clear what I should do to get the desired result, that sol3 = sol1? Many thanks!

The following line

``````q = p
``````

just assigns a different name for `p`, thus if `p` changes later, `q` also changes. I think you need

``````q = copy(p)
``````
4 Likes

Thank you for your reply. In my real use case `copy` didn’t work, got `MethodError: no method matching copy(::P)`. But

``````q = deepcopy(p)
``````

worked.

2 Likes

If the change in p happens inside a function, like bellow, I also need to do the assign of q to p in global scope (I think) so to have `sol1 == sol3`

``````...
sol1 = optimal(p)
function do(p)
q = deepcopy(p)
p = add(p, something)   # p changed
sol = optimal(p)
global p = q            # restore p
return sol
end
sol2 = do(p)
sol3 = optimal(p)
``````

Is there a better way of doing all this? Thanks in advance!

That’s expected, because you need to decide what copying your struct actually means. In your case, that’s probably:

``````Base.copy(p::P) = P(copy(p.this), copy(p.that))
``````

Sure–at the very least there’s no need to do the `global p = q` thing. Something like this should work without mutating global variables (which is almost always a code smell):

``````function foo(p)
q = copy(p)
add!(q, something)  # I'm assuming that your `add` function actually mutates its argument
return optimal(q)
end
``````

I’m assuming that your `add` function mutates its argument, which is why I’ve renamed it to `add!`. But I’m just guessing here because I can’t actually see your code.

Edit: Fixed some missing `copy()` calls in my `copy` definition

2 Likes