web-k.log

RubyやWebをメインに技術情報をのせていきます

Enumerable::lazyをちょっとだけ

| Comments

Ruby 2.0 で追加されたEnumerable::lazyをOKIソフトウェアさんのRuby 2.0 メモ: Lazy と LINQ とループ融合を参考に動かしてみました。

まずはrvmを最新にし、ruby 2.0をインストールします。

1
2
3
rvm get latest
rvm list known # ruby 2.0 が追加されている事確認
rvm install 2.0.0-preview2

で、実験です。1から30までの整数で3が含まれるもの(3, 13, 23, 30)の最初の3つを求めるには

1
2
 (1..30).map{|i| print i; i.to_s}.select{|s| print '-'; /3/ === s}.take(3)
123456789101112131415161718192021222324252627282930------------------------------=> ["3", "13", "23"]

このコードでは、

  1. map で各整数を文字列化

  2. selectで文字列に3が出現するものを正規表現で選択する。=> [“3”, “13”, “23”, “30”]

  3. takeで先頭の三つを取り出す。=> [“3”, “13”, “23”]

で、指定した範囲の最後まで読み込んでから次の処理を行う。

これに対し、lazyを用いたコードは以下。

1
2
(1..30).lazy.map{|i| print i; i.to_s}.select{|s| print '-'; /3/ === s}.take(3).to_a
1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-=> ["3", "13", "23"]

先頭の3つを読み込んだところで終了しています。 これは、結果をArrayではなくEnumerable型として返すようにmapメソッドやselectメソッドを再定義し、実際に要素の値が必要になったとき、つまり、mapの処理はselectが呼ばれたときに開始、 selectの処理はtakeに呼ばれたときに開始…というように必要なときになったら呼び出すようになっています。

Comments