1

I'm confused by the answers to this previous question Creating copies in Julia with = operator: Specifically I'm confused by the comments under StefanKarpinki's October 7th answer to that question, specifically when RedPointyJackson said

"Ok, I undestand that. But when I do b=a, it should be assignment because it's an operation in the x = ... style, right? So now I have b 'pointed' to a, and all changes in a should reflect whenever I evaluate b, don't they?" – RedPointyJackson Oct 9 '15 at 12:49

and then StefanKarpinski said

"Yes, that's correct and all of this behavior is completely in line with that. If you do a = b then any change to b also affects a. If the value bound to b is an immutable value like 42 then you can't mutate it anyway, so there's no way to tell if it was copied or referenced." – StefanKarpinski Oct 10 '15 at 4:47

Why are these previous comments suggesting that the Julia commands

a = 1; 
b = a; 
a = 2; 

will change the value of b to 2? RedPointyJackson started that thread with evidence that b will remain equal to 1!! So why are the quoted comments suggesting that the value of b will change to 2!?

user3196617
  • 156
  • 2
  • 6

2 Answers2

3

So why are the quoted comments suggesting that the value of b will change to 2!?

It looks like you misunderstood those comments.

If you do a = b then any change to b also affects a.

To be precise, this should be rephrased as "any change to the value bound to b also affects a." Note the only thing that matters here is the value to be bound, not the variable name b. Accordingly,

a = 1; # the variable name `a` is binding to the value `1`   
b = a; # the variable name `b` is binding to the value(`1`) bound to `a`
a = 2; # the variable name `a` is binding to the value `2` (`b` is still binding to `1`.)

As 1 is an immutable value and there is no way to mutate it, we have to rebind a/b if we'd like to change "their content". Here is another example:

A = [1]; # the variable name `A` is binding to the value `[1]`(an array)   
B = A; # the variable name `B` is binding to the value(`[1]`) bound to `A`
A[1] = 2; # this is called mutation. the value(`[1]`) bound to `A` has been changed to `[2]`. this value is also bound to `B`, so the "content" of `B` is changed accordingly.   
A = 1; # the variable name `A` is binding to the value `1` (`B` is still binding to `[2]`.)
Gnimuc
  • 8,098
  • 2
  • 36
  • 50
  • So if it "should be rephrased" as you say, then I did not "misunderstand it". Truth is, those comments were written confusingly and incorrectly, and so they confused me. .......................................................... For example, the comment "So now I have b 'pointed' to a, and all changes in a should reflect whenever I evaluate b, don't they?" is most definitely not true, since not "all changes" reflect in evaluation of b. Truth is: when a is re-assigned, b is unaffected. – user3196617 Apr 28 '19 at 14:42
  • And further, the other comment "if you do a = b then any change to b also affects a" is also not true since not "any change" to b affects a. Truth is: when b is re-assigned, a is unaffected. – user3196617 Apr 28 '19 at 14:48
  • 1
    I think the root cause is people often use the identifier `x` to describe two different things: the **name** "x" and the **value** bound to it. As a result, we often need to "guess" what it stands for based on the context. In this comment "all changes **in a**" should be understood as "all changes in the value bound to a". If `a` only stands for an identifier's name, obviously the only change we can do is rebinding/re-assignment, then what does "all changes" mean? This sentence itself doesn't make any sense. – Gnimuc Apr 29 '19 at 01:38
  • native speakers often can understand(guess) what a foreigner really means based on the context even if the foreigner makes big grammar mistakes. that's why I thought you misunderstood those confusing comments. – Gnimuc Apr 29 '19 at 01:44
1

I am trying to explain this issue in the following terms (from an upcoming book):

Memory and copy issues

In order to avoid copying large amount of data, Julia by default copies only the memory address of objects, unless the programmer explicitly request a so-called "deep" copy or the compiler "judges" an actual copy more efficient.

Use copy() or deepcopy() when you don't want that subsequent modifications to the copied object would apply to the original object.

In details:

Equal sign (a=b)

  • performs a name binding, i.e. binds (assigns) the entity (object) referenced by b also to the a identifier (the variable name)
  • it results that:
    • if b then rebinds to some other object, a remains referenced to the original object
    • if the object referenced by b mutates (i.e. it internally changes), so does (being the same object) those referenced by a
  • if b is immutable and small in memory, under some circumstances, the compiler would instead create a new object and bind it to a, but being immutable for the user this difference would not be noticeable

a = copy(b)

  • creates a new, "independent" copy of the object and bind it to a. This new object may however reference in turn other objects trough their memory address. In this case it is their memory address that is copied and not the referenced objects themselves.
  • it results that:
    • if these referenced objects (e.g. the individual elements of a vector) are rebound to some other objects, the new object referenced by a maintains the reference to the original objects
    • if these referenced objects mutate, so do (being the same objects) those referenced by the new object referenced by a

a = deepcopy(b)

  • everything is deep copied recursively
Antonello
  • 6,092
  • 3
  • 31
  • 56