何か着ていればいいよ

ソフトウェア技術者の日常や技術の話を書こうと思います。

Rubyの配列(あるいはオブジェクト)の振る舞いがよく分からない。

表題の件について、今日は色々はまっているのでその経緯を残しておく。

環境

OS:mac os x
ruby: ruby 2.0.0p481

状況

ruby koansのabout_dice_project.rbを解いていて以下の状況にぶち当たった。
あるクラスのメンバ変数*1を配列クラスでもっており、そのclearメソッドを使うか、別のインスタンスを使うかでランダムなはずの配列の結果が意図と異なる振る舞いをする。
と、文章で書いても意味わからないので実際のコードを抜粋。

class DiceSet
  def initialize
    @values = []
  end
  attr_accessor :values
  def roll(value)
    @values.clear
    value.times{@values << ([*1..6].sample())}
  end
end

dice = DiceSet.new

dice.roll(5)
first_time = dice.values

dice.roll(5)
second_time = dice.values

first_time == second_time # => true だけどなんで?

この場合、first_timeとsecond_timeの内容は非常に稀な可能性を除いて異なる物になることを期待しているんだけど、まったく同じ要素の配列になっちゃうのはなんでなんだぜ?
ってところがわからない。
多分知っている人が見たら一瞬なんだろうけど、自分のググリビティではぱっと何故か?という点にたどり着けなかったので現時点ではよく分かってない状況。
rollメソッド内でclearメソッドを読んでいる箇所を別の配列のインスタンスに置き換えると意図したとおり毎回異なる配列が返るのだけど…。

class DiceSet
  def initialize
    @values = []
  end
  attr_accessor :values
  def roll(value)
    @values = []
    value.times{@values << ([*1..6].sample())}
  end
end

dice = DiceSet.new

dice.roll(5)
first_time = dice.values

dice.roll(5)
second_time = dice.values

first_time == second_time # => ほとんどの場合false

しょぼい、Rubyスキルを晒すことになるけどとりあえず今はこんな感じ。

*1:C++とかJavaっぽい表現だけど、そちらの出身なので…。Ruby的にはなんて言うのかな?