.freeze 関連の問題は Object.object_id を意識して解く

Ruby Gold の .freeze に関する問題でよく考えればわかるのに間違えた!早とちり厳禁!

array = [1, 2, 3].freeze
array += [4, 5]
p array
# >> [1, 2, 3, 4, 5]

object_id で確認する

.freeze してるのに操作しようとしてるから「例外発生でしょ!」って思ってしまったけど,代入演算子 += だから別のオブジェクトとして差し替わっていて .freeze の影響は受けず,配列要素は追加される.

Object.object_id で確認すればわかる通り,代入前後で array のオブジェクト ID は変わってる.

array = [1, 2, 3].freeze
p array.object_id
array += [4, 5]
p array.object_id
# >> 70351451485280
# >> 70351451485140

<< だと NG

<< だとオブジェクト ID が変わらないので,.freeze しなければ代入できるけど,.freeze すると例外が発生する.

array = [1, 2, 3]
p array.object_id
array << 4
array << 5
p array.object_id
p array
# >> 70128528216980
# >> 70128528216980
# >> [1, 2, 3, 4, 5]
array = [1, 2, 3].freeze
p array.object_id
array << 4
array << 5
p array.object_id
p array
# ~> -:3:in `<main>': can't modify frozen Array (RuntimeError)
# >> 70337618727740

まとめ

凡ミスすると命取りになるし気を付ける!

Ruby Gold 関連