Why making a change in a copy of a variable changes the original variable?

I am so confused now. Can you explain this to me:

aa = [1,2,3]
bb = aa
bb[1,1] = 66

Output:

bb = 3-element Array{Int64,1}:
 66
  2
  3

aa = 3-element Array{Int64,1}:
 66
  2
  3

I am only making a change in bb, why aa is changing as well?

1 Like

The = operator does not make a copy. It is assigning a new variable (i.e., way to refer to an object) the same reference (actual object in memory). If you want a copy you can use copy.

julia> a = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> b = copy(a)
3-element Array{Int64,1}:
 1
 2
 3

julia> a[1] = 4
4

julia> a
3-element Array{Int64,1}:
 4
 2
 3

julia> b
3-element Array{Int64,1}:
 1
 2
 3

The isbitstype like Int are immutable and contains no references to other values. Those work a bit a different,

julia> a = 2
2

julia> b = a
2

julia> a = 1
1

julia> a
1

julia> b
2

Here is the different behaviors with mutable structs.

julia> mutable struct A
           x::Int
       end

julia> a = A(2)
A(2)

julia> b = a
A(2)

julia> a = A(1)
A(1)

julia> a
A(1)

julia> b
A(2)
julia> a = A(2)
A(2)

julia> b = a
A(2)

julia> a.x = 1
1

julia> a
A(1)

julia> b
A(1)
3 Likes

This is the only language working like this. I have never seen this before. This can causes a lot of issues though. Currently, I am giving some variables into a function and I will modify them inside the function but I don’t want them to be changed in the main function. What should I do then?

Some values are immutable. If you really want to disallow changes to arguments passed into functions, use immutable values. Arrays in a way act like pointers to mutable data. Passing an array will therefore not prevent a function from changing some of the data.

3 Likes

Python and Java both do this also. What languages are you coming from?

4 Likes

I think R make copies with the assignment operator. Still R, makes some really weird decisions such as auto conversion rules. For example, if you have a 1M element integer vector and replace an element with a character it will just make a new copy of the full vector with the character representation of the 1M elements.

1 Like

One should avoid creating copies if one does not need to. If you have a mutating function it is usually denoted with a bang magic!(obj) while magic(obj) would not modify obj.
Try this approach

julia> function magic!(obj::AbstractVector, x)
           obj[1] = x
           obj
       end
magic! (generic function with 1 method)

julia> magic(obj::AbstractVector, x) = magic!(copy(obj), x)
magic (generic function with 1 method)

julia> a = [1, 2, 3]
3-element Array{Int64,1}:
 1
 2
 3

julia> magic(a, 4)
3-element Array{Int64,1}:
 4
 2
 3

julia> a
3-element Array{Int64,1}:
 1
 2
 3
1 Like

MATLAB and Python. I didn’t know this about Python though.

So how can I pass an array or a matrix to a function without changing them in the main code?

just use copy in the function so it doesn’t reference the same objects that you pass in.

1 Like

But remember that one of the basic tenets of Julia is that copying is in general inefficient. If I have a large array, it is inefficient to make a copy, change the copy inside the function, and return it. If I can justify changing an array inside a function, I will do it, because it will avoid the cost of the copying.

7 Likes
In [1]: a = [1,2,3]

In [2]: b = a

In [3]: b[0] = 10

In [4]: a
Out[4]: [10, 2, 3]

yeah this is almost always what users want other wise it’s too painful…

Yeah, this is exactly the same as what Python does. Did you try your own example in Python?

1 Like

Is Matlab not also working the same way? It is a long time ago when I last used it and I do not have a license anymore to check.

It is better to organize your code assuming that functions never change (the contents of) their arguments unless this is explicitly documented, and thus requested by the caller.

Ideally, if your function wants to modify contents of a container, it should make a copy within the function body itself, or use a preallocated buffer. See the ! convention.

2 Likes

No, Matlab copies on assignment (it actually cheats a bit, and only makes the copy when you start modifying it).

It is one of the many frustrating things about Matlab.

4 Likes

R does it too, and it’s as horrible as you would expect (especially when it comes to threading, and/or other optimizations). See

5 Likes