0

I've come across the following concern in Ruby

a = [1, 2, 3]
b = a
b.delete_at(1)
b => [1,3]
a => [1,3]
b.object_id => 70178446287080
a.object_id => 70178446287080

So I kind of have an understanding of this. a holds a reference to an array at the object_id.

b also has a reference to that SAME position as b points to a which refers to its object_id. Basically they refer to the same thing. So if I mutate something for b, a is also mutated.

What category does this behavior fall in? Is there any readings/general practices that I can memorize so I won't have any errors in the future involving this? I know that a.dup would provide a new object at a different location so a.dup == b would be true. Also for a.dup.object_id == b.object_id.

Also, is dup and clone essentially the same thing in this situation, regardless of shallow vs deep?

user3278117
  • 95
  • 1
  • 8

1 Answers1

0

Both #dup and #clone create a shallow copy of an object. However, #clone does two things that #dup doesn't:

  • copy the singleton class of the copied object
  • maintain the frozen status of the copied object

Example for singleton:

#dup:

a = Object.new

def a.foo do
  :foo 
end

p a.foo
# => :foo

b = a.dup
p b.foo
# => undefined method `foo' for #<Object:0x007f8bc395ff00> (NoMethodError)

#clone:

a = Object.new

def a.foo do
  :foo 
end

p a.foo
# => :foo

b = a.clone
p b.foo
# => :foo

Example for frozen state:

a = Object.new

a.freeze
p a.frozen?
# => true

b = a.dup
p b.frozen?
# => false

c = a.clone
p c.frozen?
# => true

Because of the extra steps, #clone is a bit slower than #dup (but that's probably not what will make your app too slow!).

Sayuj
  • 7,464
  • 13
  • 59
  • 76