Close icon
2017月11日20日

Ruby で配列を freeze する話

Ruby で配列を freeze したかったら以下。

irb(main):001:0> LIST = ['001', '002', '003'].freeze
=> ["001", "002", "003"]

ただし上のコードで freeze されるのは LIST という配列オブジェクト自体で、配列の要素の値は freeze されない。

irb(main):002:0> LIST.frozen?
=> true
irb(main):003:0> LIST[0].frozen?
=> false
irb(main):004:0> LIST[0].class
=> String

配列オブジェクトの LIST は freeze されているけど、その要素はやっぱり freeze されていない。Ruby の .freeze メソッドは呼び出したオブジェクトを freeze する仕様なので、LIST.freeze メソッドを呼んでも、その中の要素の String オブジェクトは影響を受けない。

なので中身の String オブジェクトも含めて freeze したければ以下の魔法にしておく。

irb(main):001:0> LIST = ['001', '002', '003'].map(&:freeze).freeze
=> ["001", "002", "003"]
irb(main):002:0> LIST[0].frozen?
=> true
irb(main):003:0> LIST.frozen?
=> true

魔法と書いたけど、単に配列を定義語にそいつを map して各要素に格納されているオブジェクト毎に freeze したあと、最後に配列自体を freeze しているだけ。

なので・・・。

上の挙動なので、以下のようなこともできる。

irb(main):001:0> LIST = ['001', '002', '003'].freeze
=> ["001", "002", "003"]
irb(main):002:0> LIST.frozen?
=> true
irb(main):003:0> LIST[1].freeze
=> "002"
irb(main):004:0> LIST[1].frozen?
=> true
irb(main):005:0> LIST[0].frozen?
=> false

配列自体は freeze、また、特定の要素も freeze。上の例だと LISTの2番目の文字列は freeze されているので変更できないけど、1番目と3番目は書き換え可能。だけど配列に新しい値を入れたり、配列オブジェクト自体に破壊的操作をすることはできない。



アトトックラボとは

株式会社アトトックメンバー が技術の話、デザインの話、キャラクターの話、ときどき脱線してガジェットの話やライフハックの話など好きなことを書いています。


連載記事


最近の記事


タグ