Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

配列をfreezeする時は、ちゃんと中身もfreezeしとく

配列をfreezeする場合は

  • mapにfreezeメソッドを渡し中身を定数化
  • 配列自体をfreezeし、本体も定数化

という手順を取ります。

ためしに、最初の手順だけで止めると

str_frozen = %w(foo bar buzz).map(&:freeze)                                                                                     
#=> ["foo", "bar", "buzz"]

str_frozen[0].frozen?
#=> true

str_frozen.frozen?
#=> false

と、配列そのものは定数化していない事が確認できます。
というわけで、ちゃんと配列本体にもfreezeをかけてあげます。

ary_frozen = %w(foo bar buzz).map(&:freeze).freeze                                                                              
#=> ["foo", "bar", "buzz"]

ary_frozen.frozen?                                                                                                           
#=> true

以降は定数化されてるので、これに変更を加えようとすると

ary_frozen << "test"
# 2> RuntimeError: can't modify frozen Array

となりエラーを吐き出します。

じゃあ、本体だけfreezeするとどうなるんです?

記事を書き終わったあとに気になったので試してみました。
結果は……使えない事はないものの、要素が凍結されてるか参照するとエラーを吐きます。

buff = %w(a b c).freeze
#=> ["a", "b", "c"]

buff.frozen?
#=> true

buff[0]
#=> "a"

buff[0] = 'b'
# 2> RuntimeError: can't modify frozen Array

buff[0].forzen?
# 2>NoMethodError: undefined method `forzen?' for "a":String

参考もと

Effective Ruby

Effective Ruby