Effective Rubyを読んで気になったこと(reduce・each_with_object・inject)
途中までですが、Effective Rubyを読んでみました。
- 作者: Peter J. Jones,arton,長尾高弘
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/09
- メディア: 大型本
- この商品を含むブログ (13件) を見る
reduce
というメソッドを知らなかったです。inject
は知っていたのですが、そのエイリアスだそうです。
inject
(reduce
)と聞くと、自分ならeach_with_object
を使うかなと思いました。細かいですがinject
だとアキュムレータを返す必要があるからです。
こんなかんじです。
[1, 2, 3, 4].inject([]) do |nums, num| nums << num * 2 nums end
each_with_object
だと副作用的に更新していってくれるのでその必要はありません。
[1, 2, 3, 4].each_with_object([]) do |num, nums| nums << num * 2 end
視点を変えてみる
そもそもinject
とreduce
には発想の違いがあるようです。(非常にわかりやすい図とともに説明されています。
Rubyist Magazine map と collect、reduce と inject ―― 名前の違いに見る発想の違い)
reduce
を使うということは、「このコレクションの畳み込みをします。」というのをメソッドで自己ドキュメント的に宣言できるということです。(最低現reduceの単語の意味は知っておく必要がありますが…。)それに対しeach_with_object
は「コレクションのループと同時にこのobjectを更新していきましょう」ということしか読み取れません。畳み込む場合は、多少記述が増えてもreduce
を使うのがいい気がしました。
結論
畳み込みする(要素を足しあわせたり、条件に応じて捨てたりする)ときはreduce
、そうでなく、例えばオブジェクトのArray
からHash
に変換するみたいな場合はeach_with_object
を使うのがよさそう。inject
はどうしよう><