Enumerable は何をしてくれるモジュール?
Rubyの Enumerable モジュールは、map, select, find, take などの便利な配列風メソッドを提供してくれるモジュールです。
どういう時に使う?
Railsを使っていたら使う機会がないと思うのですが、以下の場合に使用するのかなと思っています。
- 自作のクラスを「配列っぽく」使いたいとき
- データを逐次処理・フィルタ・変換したい時
- クラスの中の配列っぽいデータにメソッドを委譲せずに使いたいとき
スクリプトを実行する時やバッチ処理を実行する時に使えるかな?くらいの感覚だと思っています。
1. 自作のクラスを「配列っぽく」使いたいとき,クラスの中の配列っぽいデータにメソッドを委譲せずに使いたいとき
Enumerable
を使用しない場合
class Alphabet
attr_reader :alphabet
def initialize
@alphabet = ("A".."Z").to_a
end
end
a = Alphabet.new
p a.alphabet.map(&:downcase) # => ["a", "b", ..., "z"]
Enumerable
を使用する場合
class Alphabet
include Enumerable
def each
("A".."Z").each { |ch| yield ch }
end
end
a = Alphabet.new
p a.map(&:downcase) # => ["a", "b", ..., "z"]
Enumerable
を使用すると、インスタンスに対してmap
メソッドを使用することができるようになります。
2. データを逐次処理・フィルタ・変換したい時
Enumerable
を使用しない場合
class Counter
attr_reader :counter
def initialize
@counter = (1..Float::INFINITY).to_a
end
end
c = Counter.new
p c.counter.lazy.select(&:even?).first(5) # => [2, 4, 6, 8, 10]
Enumerable
を使用する場合
class Counter
include Enumerable
def each
(1..Float::INFINITY).each { |i| yield i }
end
end
counter = Counter.new
p counter.lazy.select(&:even?).first(5) # => [2, 4, 6, 8, 10]
Float::INFINITYを使用する場合の処理を書きやすくなったかな?
Enumerable
を使用しない場合は無理やり書いてます。(実行したら、止めない限りずっと処理が続きます。)
まとめ
簡単にしか書かなかったですが、Enumerable
モジュールを使用することで、ちょっと簡単にループ処理が書けるようになったりするっぽいです。
制約として、each
メソッドをインクルードしたクラスに定義する必要がありますが、each
メソッドをカスタマイズすることで価値が上がるモジュールなのかなと感じました。
い