# Weird behavior of for loop+copy syntax

**URL:** <https://discourse.julialang.org/t/weird-behavior-of-for-loop-copy-syntax/114185>\
**Category:** General Usage\
**Created:** [May 13, 2024, 4:29am UTC](https://discourse.julialang.org/t/weird-behavior-of-for-loop-copy-syntax/114185 "2024-05-13T04:29:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ttx002000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ttx002000/32/208489_2.png) [@ttx002000](https://discourse.julialang.org/u/ttx002000)\
**Post date:** [May 13, 2024, 4:29am UTC](https://discourse.julialang.org/t/weird-behavior-of-for-loop-copy-syntax/114185/1 "2024-05-13T04:29:31Z")

</div>

Dear All  
Here is a minimum working example:

```julia
function test_func()
   A=[zeros(Float64,2) for _ in 1:2]
   B=copy(A)
   for ja in 1:2, jb in 1:2
       (B[ja][jb],A[ja][jb])=(1.0,2.0)
       
   end
   print(B)
   print(A)
end

```

When I call this function, it prints out two matrix, with 2.0 on all its entries

 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/4/e4424bb6bf07a16f5ddfd423575469d0d29ff164.png)

Why does Julia behave in this way? When I write B=copy(A), shouldn’t they refer to different object rather than the same reference? Then when I try to assign all the entries of B to be 1, and all the entries of A to be 2, why doesn’t this grammar work?

---

<div class="post-metadata">

**Author:** ![screw\_dog](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/screw_dog/32/48119_2.png) [@screw\_dog](https://discourse.julialang.org/u/screw_dog)\
**Post date:** [May 13, 2024, 5:19am UTC](https://discourse.julialang.org/t/weird-behavior-of-for-loop-copy-syntax/114185/2 "2024-05-13T05:19:21Z")

</div>

Welcome to the trickiness of copying. In Julia (and many other languages), `copy` is a shallow copy that only duplicates the outside structure.

Here `A` is a `Vector{Vector{Float64}}` and so only the outermost `Vector` is copied, the internal `Vector{Float64}`s are not. So both `A` and `B` end up with the same contents and you get the behaviour you are experiencing.

What is confusing is that types like `Float64` aren’t references so if you `copy` a `Vector{Float64}` you do end up with distinct vectors. This can be shown with a simple example:

```julia
A = [1, 2]
B = copy(A)
A[1] = 2
B[1] == 1 # true

```

---

<div class="post-metadata">

**Author:** ![consumere](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/consumere/32/209031_2.png) [@consumere](https://discourse.julialang.org/u/consumere)\
**Post date:** [May 13, 2024, 8:51am UTC](https://discourse.julialang.org/t/weird-behavior-of-for-loop-copy-syntax/114185/3 "2024-05-13T08:51:22Z")

</div>

works with

```julia
 @doc deepcopy  

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 13, 2024, 10:56am UTC](https://discourse.julialang.org/t/weird-behavior-of-for-loop-copy-syntax/114185/4 "2024-05-13T10:56:32Z")

</div>

> [@screw\_dog](#):
>
> Here `A` is a `Vector{Vector{Float64}}` and so only the outermost `Vector` is copied, the internal `Vector{Float64}`s are not.

> [@screw\_dog](#):
>
> What is confusing is that types like `Float64` aren’t references

It’s easier and consistent to think of a shallow copy of a mutable data structure as a copy sharing elements/instances with the original.

```julia
julia> x = [1];

julia> x2 = copy(x);

julia> x[begin] === x2[begin]
true

julia> y = [[1]];

julia> y2 = copy(y);

julia> y[begin] === y2[begin]
true

```

The elements of `y` and `y2` both contain the same instance `[1]`, so mutating that instance by reassigning its element will be reflected in both `y` and `y2`. This doesn’t apply to `x`’s immutable elements.

```julia
julia> y[begin][begin] = 2; # mutates y[begin], not y

julia> y, y2
([[2]], [[2]])

```

You can mutate `x` by reassigning its element, and that will not occur to the copy `x2`. The same thing applies to `y`:

```julia
julia> x[begin] = 2;

julia> x, x2
([2], [1])

julia> y[begin] = [3];

julia> y, y2
([[3]], [[2]])

```

The confusion comes from 1) failing to tell what is being mutated, and 2) failing to distinguish a matrix of scalars from a vector of vectors. A matrix works fine:

```julia
julia> function test_func2()
          A=zeros(Float64, 2, 2) # makes a 2x2 matrix
          B=copy(A)
          for ja in 1:2, jb in 1:2
              (B[ja, jb],A[ja, jb])=(1.0,2.0) # mutates B and A, not its elements
          end
          print(B)
          print(A)
       end
test_func2 (generic function with 1 method)

julia> test_func2()
[1.0 1.0; 1.0 1.0][2.0 2.0; 2.0 2.0]

```

but so would a vector of vectors if you mutated the outer vector instead of the inner ones, though this is much worse than a proper matrix for other reasons:

```julia
julia> function test_func3()
          A=[zeros(Float64,2) for _ in 1:2]
          B=copy(A)
          for ja in 1:2
              (B[ja],A[ja])=([1.0, 1.0],[2.0, 2.0]) # mutates B and A, not its elements
          end
          print(B)
          print(A)
       end
test_func3 (generic function with 1 method)

julia> test_func3()
[[1.0, 1.0], [1.0, 1.0]][[2.0, 2.0], [2.0, 2.0]]

```

I assume it’s written this way for the purpose of a MWE, there are much better ways to make arrays filled with the same number.
