質問: ["a", "b", "c", "d", "e"] p a.slice!(1, 3) ``` 上記の実行結果は以下になります. ``` [2, 3, 4] # => [1, 5, 6, 7]にならない ["b", "c", "d"] # => ["a", "e"]にならない ``` 期待した動作をしなく,原因がわかりません. 期待した動作をするようにするにはどのようにしたら良いでしょうか. ご教授宜しくお願いします.
回答: Rubyの標準ライブラリのメソッドには * レシーバのオブジェクトのコピーに何らかの操作を加えた結果を返すもの * レシーバのオブジェクト自体を変更するもの があり、前者を「非破壊的」メソッド、後者を「破壊的」メソッドと言います。同様の処理をする非破壊的メソッドと破壊的メソッドがある場合、破壊的メソッドの方のメソッド名に"!"をつけるのが慣習となっています。 (あくまで同機能のメソッドがある場合でしかも慣習なので、一般的に「"!"がついていれば破壊的メソッド」ではないことに注意してください) `slice`/`slice!`もこのパターンで、前者は配列をスライスした結果を返し(元のオブジェクトはそのまま)、後者は呼び出したオブジェクト自体を変更します。 破壊的メソッドの戻り値が何になるかはメソッド次第なので注意が必要です。`slice!`は削除した要素を返すのですが、「処理が行われれば`self`、行わなければ`niL`」を返すものもあります。 例えば ``` str2 = str.sub(/hoge/, 'fuga') #以後str2を操作してstrは触らない ``` こういうコードで誤って`sub!`を使ったとすると、変換が行われればどちらも同じ動きをしますが、変換が行われないと`str2`は`str`のコピーが入っているつもりが実際には`nil`になります。変換がまれにしか行われない場合、これはかなりわかりにくいバグになります。 なので、非破壊的メソッドと破壊的メソッドの使い分けには十分注意してください。