A wise decision.
In practice things happens as you describe, but there is also a fundamental misunderstanding here: copy
is blind to the inner elements, it does not take different decisions based on the type of the inner elements, it always do the same thing: copying a reference to the element.
“But what about Int
s”, you may say, “they are copied by value” or yet, “changes I make to them do not reflect in the original array”. To that I have two answers:
- “changes I make to them do not reflect in the original array” – You never make changes to an
Int
s object, they are immutable. You cannot take5
and modify it. You can have anInt
field/position and modify whichInt
object is inside it, but the field/position itself is a property of the container not of the object; the object itself is never modified. This confusion arises of the old:binding
/label
/reference
versusvariable
/box
/memory-block
. - “they are copied by value” – They may, or they may not. This is just a compiler optimization. And this is not just for
Int
s but for any immutable object, if the compiler deems the object “too large to be copied” or is able to perceive it will be copied to a lot of places, it can instead copy a reference instead. As the object is immutable, it is impossible to the user to see a semantic difference: the user cannot change the object to see a change in many places. You can sometimes see a performance difference however: see this very interesting case in which the compiler is able to do an unexpectedly smart deduction.
I think we are at the binding
/label
/reference
versus variable
/box
/memory-block
again. If you can forget memory layout for a moment, the best way to see it is that copy
over a container always duplicate the container itself but the container is always a container of binding
s/label
s/reference
s. Consequently, if you copy