为什么要“替换”而不是将新对象分配给同一个变量?

时间:2016-01-21 16:26:45

标签: ruby immutability

当我偶然发现这段代码时,我正在查看Solitaire Cipher中的测验摘要:

def triple_cut
  a = @deck.index( 'A' )
  b = @deck.index( 'B' )
  a, b = b, a if a > b
  @deck.replace( [ @deck[(b + 1)..-1],
                   @deck[a..b],
                   @deck[0...a] ].flatten )
end

我不明白为什么有一个单独的方法replace。为什么不这样做呢?

@deck = @deck[(b + 1)..-1] +
        @deck[a..b] +
        @deck[0...a]

为什么要将两个单独的方法(replaceflatten)放在一起时才会遇到麻烦?我没有遇到任何问题。

3 个答案:

答案 0 :(得分:5)

  1. 通过不重新创建阵列来节省内存。
  2. 您可以在不重新分配变量的情况下引用同一个对象。

答案 1 :(得分:4)

替换/重新分配大型数组时,Array#replace似乎比分配=表现更好。

require 'benchmark'

n = 500
ary_size = 10000

replacement = ['b']*ary_size*3

Benchmark.bm do |x|
  x.report { n.times { arr = ['a']*ary_size; arr.replace(replacement)} }
  x.report { n.times { arr = ['a']*ary_size; arr = replacement}}
end

输出:

       user     system      total        real
   0.000000   0.000000   0.000000 (  0.002253)
   0.015000   0.000000   0.015000 (  0.015224)
[Finished in 0.1s]

答案 2 :(得分:4)

红宝石的美妙之处在于,在很多情况下,没有正确的方法来做事。在您的情况下,我认为您的解决方案同样有效且易于阅读。

至于replace,它的工作原理是将值复制到现有数组中,然后将其分配给不同的对象。

例如

x = [1, 2]
y = [3]
x.replace(y) # x is [3] and y is [3]
x << 5 # x is [3, 5] and y is [3]

x = [1, 2]
y = [3]
x = y # x is now pointing to the same object as y
x << 5 # both x and y are [3, 5] because they are the same object