juliavariable-assignmentmutation

After the assignment "b = a", when does changing "a" in Julia also changes "b" and when it does not?


Suppose I have run the assignment b = a in Julia. Then I change a.

In what cases does b change automatically and when not?

Notes

The answer to Creating copies in Julia with = operator covers the same central topic with different implications and fewer examples. This question seems not to appear in a search by someone who already knows that an assignment is not a "copy" in Julia. (I wrote my question and answer because it did not appear in my own search.) For those people, my question will be useful. Besides, the answer is easier to understand, and refers to the linked question at the end.

The use of "change" in the question is deliberately ambiguous. It reflects "a common confusion (in) the distinction between assignment (...) and mutation" as stated in https://docs.julialang.org/en/v1/manual/variables/#man-assignment-expressions:~:text=A%20common%20confusion%20is%20the%20distinction%20between%20assignment%20(giving%20a%20new%20%22name%22%20to%20a%20value)%20and%20mutation.


Solution

  • Assignment vs Mutation

    Suppose that, after running the assignment a=[1,2,3], we run the assignment b=a. Both a and b are names that point to the same space in memory where the array [1,2,3] resides. (The same effect results from the chained assignment b=a=[1,2,3].)

    The mutation a[1] = 42 changes the mutable structure [1,2,3] to [42,2,3]. Now, both a and b refer to the new value [42,2,3].

    A subsequent assignment a = 3.14159 does not change the array [42,2,3]. It simply binds the name a to a different object (a scalar) that lives in a separate memory location. The array [42,2,3] is still accessible via the name b. Thus, executing a makes the REAPL display 3.14159, and executing b makes the REAPL display [42,2,3].

    Therefore, after b=a, where a is a mutable structure, any mutation of an element of a affects the value returned by b. If the change in a is not a mutation but the assignment of a separate value to the name a, the value returned by b continues to be the same. Moreover, if all the elements as such of a are changed, so are the elements of the mutable structure returned by b. Example:

    x = [1 2 3] ;
    
    y = x       ;
    
    x .= [4 5 6];    # Broadcasting changes the elements. The name x is not bound to a separate array.
    
    julia> print(x)                                                                                                                                                           
    [4 5 6]
    
    julia> print(y)
    [4 5 6]          # Therefore, y returns the same array with modified elements.
    

    Compare the previous block of code with the next:

    x = [1 2 3] ;
    
    y = x       ;
    
    x = [4 5 6];    # Julia binds the name x to a separate array.
    
    julia> print(x)                                                                                                                                                           
    [4 5 6]
    
    julia> print(y)
    [1 2 3]          # Therefore, Julia did not modify the array y refers to.
    

    Please, read the answer to Creating copies in Julia with = operator by one of the creators of Julia.