# Reference versus copy

I create a simple MWE to demonstrate some kind of reference problem which is leading to unwanted behavior when creating matrices with function elements. Here is the code:

``````function test()
zfcts = Any[t -> 0., t -> 0.]
fcts = Any[t -> sin(t), t -> cos(t)]
g = Any[]
push!(g, zfcts)
push!(g, zfcts)
g[1][1] = fcts[1]  # sin
g[2][1] = fcts[2]  # cos
x = 2.1
@show g[1][1](x)
@show (g[2][1](x))
@show (g[1] === g[2])  # Should  not be true!!!  <<<<<<
@show (g[1][1] === g[2][1])  # true
@show (g[1][2] === g[2][2])  # true
@show (g[1][1] === g[1][2])  # true
@show (fcts[1] === fcts[2])  # false (as it should be)
end

test()
``````

I expect

``````g[1][1] = sin(2.1)
g[2][[1] = cos(2.1)
``````

However, the results are always the same, and equal to `fcts[2]`, the second function define in the `fcts` list. I thought that `push!` did a copy.

Here is the code output:

``````> test()
((g[1])[1])(x) = -0.5048461045998576
((g[2])[1])(x) = -0.5048461045998576
g[1] === g[2] = true
(g[1])[1] === (g[2])[1] = true
(g[1])[2] === (g[2])[2] = true
(g[1])[1] === (g[1])[2] = false
fcts[1] === fcts[2] = false
false
``````

As usual, any insight is appreciated. I feel as if I should understand this coming from a C++ background, but I clearly am missing something important about functions and `push!`. Thanks.

Your title implies you know exactly whatâ€™s going on here?

`g` is a vector containing two references to the same vector. When you change the first element of that vector, it changes, no matter which reference you use to access it.

My title indicates that I â€śshouldâ€ť know what is going on.
I just solve the problem (thanks for the push):

``````push!(g, copy(zfcts))
push!(g, copy(zfcts))
``````

The rest of the code is the same.

Where did you read that `push!` copies? I canâ€™t find that in the documentation. I would try it, but it appears you already have.

Does `push!(g, copy(zfcts))` work?

1 Like

Yes, simply copying the list of functions inside the `push!` did the trick. Regarding operation of the push, I just assumed. I do not check every little detail in the documentation. I guess it does do a copy: what was copied was the pointer to the beginning of the list of functions (using C++ lingo).

Passing arguments in Julia (as for most languages) works just like assignment (`=`): it binds a
new name to the same object, it does not copy the object. This not a little detail â€” it is fundamental to how the language works.

(Of course, a function like `push!` could internally call `copy` on its argument before storing it in a data structure, but this is the exception rather than the rule.)

(Nor is Juliaâ€™s behavior particularly unusual among languages here.)

4 Likes