# Unexpected change of a function argument (array) - bug or feature?

**URL:** <https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [April 26, 2022, 10:33am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042 "2022-04-26T10:33:22Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Friedrich](https://avatars.discourse-cdn.com/v4/letter/f/eb9ed0/32.png) [@Friedrich](https://discourse.julialang.org/u/Friedrich)\
**Post date:** [April 26, 2022, 10:33am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/1 "2022-04-26T10:33:22Z")

</div>

When doing some first coding with Julia, I run into an issue that a function argument was changed unexpectedly. I could boil the problem down to the following lines of code:

function myfunc(f,n)  
q = f  
for k in 1:n  
q[k] += + 1.1  
end  
return q  
end

n = 1  
f = ones(1)  
println(“f =”,f)  
my\_q = myfunc(f,n)  
println(“After calling of myfunc(f,n) f is modified:”)  
println(“f =”,f)  
=========== output ========  
f =[1.0]  
After calling of myfunc(f,n) f is modified:  
f =[2.1]

My question is why f in myfunc(f,n) is changed from 1.0 to 2.1? This is completely unexpected for me, because the function myfunc() should calculate q but should not change the argument f.

I’m not sure if this is a bug or a feature of Julia. I’ve used Julia version 1.7.1.

Any comments?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 26, 2022, 10:37am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/2 "2022-04-26T10:37:29Z")

</div>

It’s a feature.

When you type `q = f` you are making `q` point to the same array as `f`. So whatever changes you make to `q` are also visible in `f`. This is extremely useful, but you must be aware of it.

Whenever `f` is a mutable data structure, `q = f` followed by mutation of `q` will be visible in `f`.

If you want to avoid this, write `q = copy(f)` instead. (In some cases you even need `q = deepcopy(f)`.)

BTW: read here to see how to format your code nicely: [Please read: make it easier to help you](https://discourse.julialang.org/t/please-read-make-it-easier-to-help-you/14757)

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [April 26, 2022, 10:51am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/3 "2022-04-26T10:51:44Z")

</div>

What does `copy` do compared to `deepcopy`?

Kind regards

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [April 26, 2022, 10:53am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/4 "2022-04-26T10:53:48Z")

</div>

It’s helpful to read the docs in this scenario:

```julia
help?> deepcopy
search: deepcopy

  deepcopy(x)

  Create a deep copy of x: everything is copied recursively, resulting in
  a fully independent object. For example, deep-copying an array produces
  a new array whose elements are deep copies of the original elements.
  Calling deepcopy on an object should generally have the same effect as
  serializing and then deserializing it.

  While it isn't normally necessary, user-defined types can override the
  default deepcopy behavior by defining a specialized version of the
  function deepcopy_internal(x::T, dict::IdDict) (which shouldn't
  otherwise be used), where T is the type to be specialized for, and dict
  keeps track of objects copied so far within the recursion. Within the
  definition, deepcopy_internal should be used in place of deepcopy, and
  the dict variable should be updated as appropriate before returning.

```

---

<div class="post-metadata">

**Author:** ![Friedrich](https://avatars.discourse-cdn.com/v4/letter/f/eb9ed0/32.png) [@Friedrich](https://discourse.julialang.org/u/Friedrich)\
**Post date:** [April 26, 2022, 11:02am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/5 "2022-04-26T11:02:23Z")

</div>

Thank’s a lot for your swift answer!

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [April 26, 2022, 11:10am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/6 "2022-04-26T11:10:31Z")

</div>

Maybe a follow up question is then; for which cases would one want to use “copy” only?

Seems to me that copying the outer shell but keeping the inner references, would not have any practical use case? (I.e. I am asking; when would I prefer to use “copy” and not “deepcopy”?)

Kind regards

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 26, 2022, 11:39am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/7 "2022-04-26T11:39:35Z")

</div>

It’s a good question. Someone recently suggested that they should be called `copy` and `shallowcopy`. I have noticed that `copy` is (ever so slightly) faster and allocates less than `deepcopy` for `Float64` array. Which is strange. I would have thought that `deepcopy(::Array{Float64})` dispatched to `copy`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 26, 2022, 11:43am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/8 "2022-04-26T11:43:38Z")

</div>

There is an old Julia issue somewhere where Jeff and Tim Holy agree that `deepcopy` is sort of a lower level function that should rarely be used. I didn’t understand the arguments, but if they agreed, I agree 😊 . ~~(couldn’t find the issue right now).~~

Found it: [Should `copy` be renamed `shallowcopy`? · Issue #42796 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/42796#issuecomment-951232853)

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [April 26, 2022, 11:48am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/9 "2022-04-26T11:48:03Z")

</div>

I think I get it now. Using copy you keep the references, but actual values are not referenced? Like this example:

```julia
a = [1.0;2;3;4]

b = copy(a)

a[1] = 5

# We observe that b[1] is still 1
println(b)

```

Actually I still don’t understand it 🙂

Kind regards

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 26, 2022, 11:52am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/10 "2022-04-26T11:52:53Z")

</div>

The difference is if the _elements_ of the container are mutable:

```julia
julia> x = [[1,2], [3,4] ] # array of arrays
2-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4]

julia> y = deepcopy(x);

julia> y[1][1] = 0
0

julia> x # is preserved
2-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4]

julia> y = copy(x);

julia> y[1][1] = 0
0

julia> x # now it changed
2-element Vector{Vector{Int64}}:
 [0, 2]
 [3, 4]

```

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [April 26, 2022, 11:55am UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/11 "2022-04-26T11:55:48Z")

</div>

Okay I see, thanks!

For my use cases I always want to **cut** the connections, so I think I will stick to deepcopy always - copy makes me a bit uneasy, since I cannot figure out when it is useful to have the same underlying object with two names.

Kind regards

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 26, 2022, 12:01pm UTC](https://discourse.julialang.org/t/unexpected-change-of-a-function-argument-array-bug-or-feature/80042/12 "2022-04-26T12:01:55Z")

</div>

> [@Ahmed\_Salih](#):
>
> I cannot figure out when it is useful to have the same underlying object with two names.

In “flat code” it is not very useful, probably. But that is consistent with what happens on function calls, in which mutable structure are not copied (which would imply possibly huge allocations in every call):

```julia
julia> f(x) = x .= .+ 1 # mutates x
f (generic function with 1 method)

julia> a = zeros(3);

julia> f(a);

julia> a
3-element Vector{Float64}:
 1.0
 1.0
 1.0

```

Thus, for a mutable structure, the _label_ assigned to it is just a label. And some care has to be taken with that.

The same happens if you share a big array within two structures:

```julia
julia> struct A
           x::Vector{Float64}
       end

julia> struct B
           x::Vector{Float64}
       end

julia> a = A(rand(3)); # could be very large

julia> b = B(a.x);

julia> a.x
3-element Vector{Float64}:
 0.008402191874595566
 0.027938927073541286
 0.8813538319613927

julia> a.x[1] = 0.
0.0

julia> b.x
3-element Vector{Float64}:
 0.0
 0.027938927073541286
 0.8813538319613927

```

This is about being efficient in memory management.
