Use [].replace to make a copy of an array

前端 未结 2 1599
星月不相逢
星月不相逢 2021-01-16 07:49

I have a class where I was using the Array#shift instance method on an instance variable. I thought I made a \"copy\" of my instance variable but in fact I hadn

相关标签:
2条回答
  • 2021-01-16 08:08

    The preferred method is dup

    • use array.dup whenever you need to copy an array
    • use array.map(&:dup) whenever you need to copy a 2D array

    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.

    0 讨论(0)
  • 2021-01-16 08:15

    This is the tricky concept of mutability in ruby. In terms of core objects, this usually comes up with arrays and hashes. Strings are mutable as well, but this can be disabled with a flag at the top of the script. See What does the comment "frozen_string_literal: true" do?.

    In this case, you can call dup, deep_dup, clone easily to the same effect as replace:

    ['some', 'array'].dup
    ['some', 'array'].deep_dup
    ['some', 'array'].clone
    Marshal.load Marshal::dump(['some', 'array'])
    

    In terms of differences, dup and clone are the same except for some nuanced details - see What's the difference between Ruby's dup and clone methods?

    The difference between these and deep_dup is that deep_dup works recursively. For example if you dup a nested array, the inner array will not be cloned:

      a = [[1]]
      b = a.clone
      b[0][0] = 2
      a # => [[2]]
    

    The same thing happens with hashes.

    Marshal.load Marshal::dump <object> is a general approach to deep cloning objects, which, unlike deep_dup, is in ruby core. Marshal::dump returns a string so it can be handy in serializing objects to file.

    If you want to avoid unexpected errors like this, keep a mental index of which methods have side-effects and only call those when it makes sense to. An explanation point at the end of a method name indicates that it has side effects, but others include unshift, push, concat, delete, and pop. A big part of fuctional programming is avoiding side effects. You can see https://www.sitepoint.com/functional-programming-techniques-with-ruby-part-i/

    0 讨论(0)
提交回复
热议问题