3

I read in another answer It's preferred to use array.map(&:dup):

Don't use the marshalling trick unless you really want to deep copy an entire object graph. Usually you want to copy the arrays only but not the contained elements.

Would love to see an example illustrating the difference between these two methods.

Besides the syntax it looks to me like they are doing the same thing.

Curious to learn more about the differences between Marshal and #dup.

    arr = [ [['foo']], ['bar']]
    foo = arr.clone
    p arr #=> [[["foo"]], ["bar"]]
    p foo #=> [[["foo"]], ["bar"]]
    foo[0][0] = 42
    p arr #=> [[42], ["bar"]]
    p foo #=> [[42], ["bar"]]

    arr = [ [['foo']], ['bar']]
    foo = Marshal.load Marshal.dump arr
    p arr #=> [[["foo"]], ["bar"]]
    p foo #=> [[["foo"]], ["bar"]]
    foo[0][0] = 42
    p arr #=> [[["foo"]], ["bar"]]
    p foo #=> [[42], ["bar"]]

    arr = [ [['foo']], ['bar']]
    foo = arr.map(&:dup)
    p arr #=> [[["foo"]], ["bar"]]
    p foo #=> [[["foo"]], ["bar"]]
    foo[0][0] = 42
    p arr #=> [[["foo"]], ["bar"]]
    p foo #=> [[42], ["bar"]]
Community
  • 1
  • 1
mbigras
  • 7,664
  • 11
  • 50
  • 111
  • 1
    `array.map(&:dup)` is good enough, since map creates a copy anyway, the additional dup was a typo in my other answer – akuhn Jan 20 '17 at 23:13

1 Answers1

0

The marshal trick also clones the elements of the array

array = [[Object.new]]

Check object_id of the element before and after the copy

array.first.first.object_id
# => 70251489489120

array.map(&:dup).first.first.object_id
# => 70251489489120 -- the same

(Marshal.load Marshal.dump array).first.first.object_id
# => 70251472965580 -- different object!

Don't use the marshalling trick unless you really want to deep copy an entire object graph. Usually you want to copy the arrays only but not the contained elements.

akuhn
  • 27,477
  • 2
  • 76
  • 91