0

Array から継承するクラスがあります (実際には、多次元配列の単なるマスクです)。to_aそのメソッドをオーバーライドしたい:

def to_a
    self.each.with_index { |el, i| el.map {|j| j} }
end

しかし、これは物事を台無しにします:私が自分の機能をテストしようとすると:

it 'should be non destructive' do
    a_board = Representation.new(@a_size)
    a_clean_board = Representation.new(@a_size)
    expect(a_board).to eq(a_clean_board)

    # Try to modify a_board
    arr = a_board.to_a
    arr.pop
    a_board.to_a.pop

    # Check that it stayed equal to a_clean_board
    expect(a_board).to eq(a_clean_board)
end

両方の呼び出しpopで、元のボードに副作用が生じます。

どうすればこれを回避できますか?

4

1 に答える 1

2

おそらく、同じオブジェクトへの参照を返すためです。これを回避するには、map代わりにeach使用するか、最後に .dup を使用します。

UPD

私が言ったように、ただ地図を使ってください。意図的に副作用がない関数型プログラミングのように。例:

class WrappedArr < Array
  def to_a
    map { |el| el.map {|el2| el2 } }
  end
end

w_arr = WrappedArr.new([[1,2], [2,3]])
# => [[1, 2], [2, 3]]

2.0.0p247 :012 > w_arr.to_a.object_id # always different as it is different object
#=> 70318090081080
2.0.0p247 :013 > w_arr.to_a.object_id
# => 70318095088040
2.0.0p247 :014 > w_arr.to_a.object_id
# => 70318095081540

# final test
2.0.0p247 :015 > w_arr.to_a.pop
# => [2, 3]
2.0.0p247 :016 > w_arr
# => [[1, 2], [2, 3]]
于 2013-10-13T11:23:05.230 に答える