Ruby 2.1.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Enumerator::Lazyクラス

class Enumerator::Lazy

クラスの継承リスト: Enumerator::Lazy < Enumerator < Enumerable < Object < Kernel < BasicObject

要約

map や select などのメソッドの遅延評価版を提供するためのクラス。

動作は通常の Enumerator と同じですが、以下のメソッドが遅延評価を行う (つまり、配列ではなく Enumerator を返す) ように再定義されています。

Lazyオブジェクトは、Enumerable#lazyメソッドによって生成されます。

Lazyから値を取り出すには、Enumerator::Lazy#force または Enumerable#first を呼びます。

例:

# 二乗して偶数になるような整数を、小さい方から5個表示する
p (1..Float::INFINITY).lazy.select{|n| (n**2).even?}.first(5)
# LTSV (http://ltsv.org/) 形式のログファイルから検索を行う
# Enumerator::Lazy#map は配列ではなく Enumerator を返すため、
# 巨大な配列を確保しようとしてメモリを使い切ったりはしない
open("log.txt"){|f|
  f.each_line.lazy.map{|line|
    Hash[line.split(/\t/).map{|s| s.split(/:/, 2)}]
  }.select{|hash|
    hash["req"] =~ /GET/ && hash["status"] == "200"
  }.each{|hash|
    p hash
  }
}

目次

特異メソッド
new
インスタンスメソッド
chunk collect map collect_concat flat_map drop drop_while enum_for to_enum find_all select force grep lazy reject slice_before take take_while zip

特異メソッド

new(obj, size=nil) {|yielder, *values| ... } -> Enumerator::Lazy[permalink][rdoc]

Lazy Enumerator を作成します。Enumerator::Lazy#force メソッドなどに よって列挙が実行されたとき、objのeachメソッドが実行され、値が一つずつ ブロックに渡されます。ブロックは、yielder を使って最終的に yield される値を 指定できます。

Enumerable#filter_map と、その遅延評価版を定義する例:

module Enumerable
  def filter_map(&block)
    map(&block).compact
  end
end

class Enumerator::Lazy
  def filter_map
    Lazy.new(self) do |yielder, *values|
      result = yield *values
      yielder << result if result
    end
  end
end

(1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
    # => [4, 16, 36, 64, 100]
[EXCEPTION] ArgumentError:
引数を指定しなかった場合、ブロックを指定しなかった場合に発生します。

[SEE_ALSO] Enumerator.new

インスタンスメソッド

chunk {|elt| ... } -> Enumerator::Lazy[permalink][rdoc]
chunk(initial_state) {|elt, state| ... } -> Enumerator::Lazy

Enumerable#chunk と同じですが、配列ではなく Enumerator::Lazy を返します。

[SEE_ALSO] Enumerable#chunk

map {|item| ... } -> Enumerator::Lazy[permalink][rdoc]
collect {|item| ... } -> Enumerator::Lazy

Enumerable#map と同じですが、配列ではなくEnumerator::Lazy を返します。

[EXCEPTION] ArgumentError:
ブロックを指定しなかった場合に発生します。

[SEE_ALSO] Enumerable#map

flat_map {|item| ... } -> Enumerator::Lazy[permalink][rdoc]
collect_concat {|item| ... } -> Enumerator::Lazy

ブロックの実行結果をひとつに繋げたものに対してイテレートするような Enumerator::Lazy のインスタンスを返します。

["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force
#=> ["f", "o", "o", "b", "a", "r"]

ブロックの返した値 x は、以下の場合にのみ分解され、連結されます。

それ以外のときは、x は分解されず、そのままの値として使われます。

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force
#=> [{:a=>1}, {:b=>2}]
[EXCEPTION] ArgumentError:
ブロックを指定しなかった場合に発生します。

[SEE_ALSO] Enumerable#flat_map

drop(n) -> Enumerator::Lazy[permalink][rdoc]

Enumerable#drop と同じですが、配列ではなくEnumerator::Lazy を返します。

[PARAM] n:
要素数を指定します。
[EXCEPTION] ArgumentError:
n に負の数を指定した場合に発生します。

[SEE_ALSO] Enumerable#drop

drop_while -> Enumerator::Lazy[permalink][rdoc]
drop_while {|item| ... } -> Enumerator::Lazy

Enumerable#drop_while と同じですが、配列ではなくEnumerator::Lazy を返します。

[SEE_ALSO] Enumerable#drop_while

to_enum(method = :each, *args) -> Enumerator::Lazy[permalink][rdoc]
enum_for(method = :each, *args) -> Enumerator::Lazy
to_enum(method = :each, *args) {|*args| block} -> Enumerator::Lazy
enum_for(method = :each, *args) {|*args| block} -> Enumerator::Lazy

Object#to_enum と同じですが、Enumerator::Lazy を返します。

to_enum は「ブロック付きで呼ぶとループを実行し、ブロックを省略した場合は Enumerator を返す」ようなメソッドを定義するときによく使われます。 このときに lazy 性が正しく引き継がれるように、Lazy#to_enum は 素のEnumerator ではなく Enumerator::Lazy を返すようになっています。

例:

module Enumerable
  # 要素をn回ずつ繰り返すメソッド
  # 例:[1,2,3].repeat(2)  #=> [1,1,2,2,3,3]
  def repeat(n)
    raise ArgumentError if n < 0
    if block_given?
      each do |*val|
        n.times { yield *val }
      end
    else
      to_enum(:repeat, n)
    end
  end
end

r = 1..10
p r.map{|n| n**2}.repeat(2).first(5)
#=> [1, 1, 4, 4, 9]

r = 1..Float::INFINITY
p r.lazy.map{|n| n**2}.repeat(2).first(5)
#=> [1, 1, 4, 4, 9]

# Lazy#to_enum のおかげで、repeat の返り値は
# もとが Enumerator のときは Enumerator に、
# もとが Lazy のときは Lazy になる
select {|item| ... } -> Enumerator::Lazy[permalink][rdoc]
find_all {|item| ... } -> Enumerator::Lazy

Enumerable#select と同じですが、配列ではなくEnumerator::Lazy を返します。

[EXCEPTION] ArgumentError:
ブロックを指定しなかった場合に発生します。

[SEE_ALSO] Enumerable#select

force(*args) -> [object][permalink][rdoc]

全ての要素を含む配列を返します。Lazy から実際に値を取り出すのに使います。

Enumerable#to_a のエイリアスです。

grep(pattern) {|item| ... } -> Enumerator::Lazy[permalink][rdoc]

Enumerable#grep と同じですが、配列ではなくEnumerator::Lazy を返します。

[SEE_ALSO] Enumerable#grep

lazy -> self[permalink][rdoc]

self を返します。

reject {|item| ... } -> Enumerator::Lazy[permalink][rdoc]

Enumerable#reject と同じですが、配列ではなくEnumerator::Lazy を返します。

[EXCEPTION] ArgumentError:
ブロックを指定しなかった場合に発生します。

[SEE_ALSO] Enumerable#reject

slice_before(pattern) -> Enumerator::Lazy[permalink][rdoc]
slice_before {|elt| bool } -> Enumerator::Lazy
slice_before(initial_state) {|elt, state| bool } -> Enumerator::Lazy

Enumerable#slice_before と同じですが、配列ではなく Enumerator::Lazy を返します。

[SEE_ALSO] Enumerable#slice_before

take(n) -> Enumerator::Lazy[permalink][rdoc]

Enumerable#take と同じですが、配列ではなくEnumerator::Lazy を返します。

n が大きな数 (100000とか) の場合に備えて再定義されています。 配列が必要な場合は Enumerable#first を使って下さい。

[PARAM] n:
要素数を指定します。
[EXCEPTION] ArgumentError:
n に負の数を指定した場合に発生します。

[SEE_ALSO] Enumerable#take

take_while -> Enumerator::Lazy[permalink][rdoc]
take_while {|item| ... } -> Enumerator::Lazy

Enumerable#take_while と同じですが、配列ではなくEnumerator::Lazy を返します。

[SEE_ALSO] Enumerable#take_while

zip(*lists) -> Enumerator::Lazy[permalink][rdoc]
zip(*lists) {|v1, v2, ...| ... } -> nil

Enumerable#zip と同じですが、配列ではなくEnumerator::Lazy を返します。

ただし一貫性のため、ブロック付きで呼び出した場合は Enumerable#zip と 同じ挙動になります。

[SEE_ALSO] Enumerable#zip