#概要
配列からnilである要素を取り除いた新しい要素を返すメソッドcompactですが、compact!となにが違うのかとおもいました。
リファレンスには「!」がつくほうはレシーバ自身を変更するメソッドとありました。
では、「レシーバ自身を変更する」とはどういうことなのでしょうか
#レシーバとは
レシーバとはメソッドを実行するオブジェクトのことです。
下記だと、.の左側のarrayです。
array.compact
array.compact!
#レシーバ自身を変更するとは
レシーバとはメソッドを実行するオブジェクトのことでしたので、「レシーバ自身を変更する」とは、このオブジェクトが変更されるということになります。
object_idをみてみます。
fruits = ["apple", nil, "orange", nil, nil, "banana"]
puts fruits.object_id
fruits = fruits.compact
puts fruits.object_id
70311962445680
70311962445540
まずは「!」がないほうですが、idが違います。
つまり、配列fruitsから、compactメソッドによりnilを除いた新しい配列fruitsができたことになります。
次は「!」をつけます。
fruits = ["apple", nil, "orange", nil, nil, "banana"]
puts fruits.object_id
fruits = fruits.compact!
puts fruits.object_id
70332086281520
70332086281520
idが同じです。
つまり、配列fruits自身が変更されたことになります。
これがレシーバ自身(今回でいうとfruits)を変更するの正体でした。
#まとめ
レシーバ自身を変更とは破壊的メソッドということでした。
今回は「!」をつけるつけないで、参照元から変更するかしないかを選択できます。
「!」をつけ参照元から変更するメリットは、メモリの節約ってところでしょうか。