0

While writing a program I discovered something interesting. If I define a = b, any changes I << onto b reflect in a, and vice-versa.

Does Ruby not create a duplicate autonomous copy of b and store it differently in a?

If not, how do I store an untampered snapshot of an array at a specific point in time, while I carry on operations on the main array?

>> a = b = [0, 1]
=> [0, 1]
>> a
=> [0, 1]
>> b
=> [0, 1]
# so far so good
>> a << 2
=> [0, 1, 2]
>> a
=> [0, 1, 2]
>> b
=> [0, 1, 2]
# huh?! that can't be right, lemme try this the other way around
>>  b << 3
=> [0, 1, 2, 3]
>> a
=> [0, 1, 2, 3]
>> b
=> [0, 1, 2, 3]
# what is going on here?!
Amin Shah Gilani
  • 8,675
  • 5
  • 37
  • 79
  • 1
    As a side note, read this: http://stackoverflow.com/questions/1872110/is-ruby-pass-by-reference-or-by-value – Nic Nilov Jun 24 '16 at 14:24

3 Answers3

3

Use Object#dup.

NB It does create a shallow copy; to create a deep copy one needs to implement the copy herself.

▶ b = [0, 1]
#⇒ [ 0, 1 ]
▶ a = b.dup
#⇒ [ 0, 1 ]
▶ b << 2
#⇒ [ 0, 1, 2 ]
▶ a
#⇒ [ 0, 1 ]

To make frozen and tainted copy, use Object#clone.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
1

a and b point to the same object in memory. If you want a copy of an object without affect the original one you can do

b = a.dup
Ursus
  • 29,643
  • 3
  • 33
  • 50
0

Let me try to clarify exactly what's going on here. This is the basic concept of references, as implemented by many languages. When you create, say, "an array," that array-value is an anonymous memory-object, and in your code both a and b refer to the same object. The language uses some variation of "reference counting" to keep track of how many references exist, so as to know when values have been "orphaned" and can be garbage-collected.

This so-called "shallow copying" is very efficient and it is often exactly what is wanted. So, it's what these languages do by default.

When you create a "deep copy," you are consciously duplicating the anonymous memory-object. Now, a points to one, and b points to another object that is (at that instant in time) a snapshot of the first. A time-consuming process by comparison, and, of course, it allocates more memory. Now, changes made to one array will (of course) not be reflected in the other, since they are now two entirely distinct things. Since this is a less-common thing to do, the language provides some explicit way for you to designate that you want to do this.

Ruby ... PHP ... Perl ... ... ... almost everybody does something like this.

(And, en passant, let me also say that they implement "strong" vs. "weak" references. But, that's another story for another day.)

EDIT: This response is partially incorrect! Kindly note the correction that was subsequently made in the first comment attached to this post. (And, "thank you for setting me straight!") The key point ( and it IS a key point ...), has to do with what the anonymous memory-objects aforementioned might contain. (They might, themselves, contain "references." Arrays often do! So, you could wind up with "two separate memory objects" which refer to the same things. Ergo, even though they are, indeed, "two entirely separate objects," they still can conflict with one another when actually used in your program. (And, heh, have fun debugging such things.)

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41
  • Shallow copying and reference copying are different things, `a = b` means both `a` and `b` reference the same object, shallow copy (`a = b.dup`) creates another object, but internal references are not dup’ed. Deep copy means that even deeply nested objects are duplicated. – Aleksei Matiushkin Jun 24 '16 at 14:39
  • Excellent point, mudasobwa. I think you should make that an "answer" to call more attention to it, and so that I can up-vote it. – Mike Robinson Jun 24 '16 at 15:06
  • Feel free to put it in your answer. – Aleksei Matiushkin Jun 24 '16 at 15:06
  • I just did. :-) Please review that answer as just-amended and be sure if my "Edit" paragraph reads rightly. Thanks again. – Mike Robinson Jun 24 '16 at 15:07