Class: Enumerator::Lazy
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
| Class Chain: 
          self,
           ::Enumerator | |
| Instance Chain: 
          self,
           ::Enumerator,::Enumerable | |
| Inherits: | Enumerator 
 | 
| Defined in: | enumerator.c, enumerator.c | 
Overview
Lazy is a special type of ::Enumerator, that allows constructing chains of operations without evaluating them immediately, and evaluating values on as-needed basis. In order to do so it redefines most of ::Enumerable methods so that they just construct another lazy enumerator.
Lazy can be constructed from any ::Enumerable with the Enumerable#lazy method.
lazy = (1..Float::INFINITY).lazy.select(&:odd?).drop(10).take_while { |i| i < 30 }
# => #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:select>:drop(10)>:take_while>The real enumeration is performed when any non-redefined ::Enumerable method is called, like Enumerable#first or Enumerable#to_a (the latter is aliased as #force for more semantic code):
lazy.first(2)
#=> [21, 23]
lazy.force
#=> [21, 23, 25, 27, 29]Note that most ::Enumerable methods that could be called with or without a block, on Lazy will always require a block:
[1, 2, 3].map       #=> #<Enumerator: [1, 2, 3]:map>
[1, 2, 3].lazy.map  # ArgumentError: tried to call lazy map without a blockThis class allows idiomatic calculations on long or infinite sequences, as well as chaining of calculations without constructing intermediate arrays.
Example for working with a slowly calculated sequence:
require 'open-uri'
# This will fetch all URLs before selecting
# necessary data
URLS.map { |u| JSON.parse(URI.open(u).read) }
  .select { |data| data.key?('stats') }
  .first(5)
# This will fetch URLs one-by-one, only till
# there is enough data to satisfy the condition
URLS.lazy.map { |u| JSON.parse(URI.open(u).read) }
  .select { |data| data.key?('stats') }
  .first(5)Ending a chain with “.eager” generates a non-lazy enumerator, which is suitable for returning or passing to another method that expects a normal enumerator.
def active_items
  groups
    .lazy
    .flat_map(&:items)
    .reject(&:disabled)
    .eager
end
# This works lazily; if a checked item is found, it stops
# iteration and does not look into remaining groups.
first_checked = active_items.find(&:checked)
# This returns an array of items like a normal enumerator does.
all_checked = active_items.select(&:checked)Class Method Summary
- 
    
      .new(obj, size = nil) {|yielder, *values| ... } 
    
    constructor
    Creates a new Lazyenumerator.
::Enumerator - Inherited
| .new | Creates a new  | 
| .produce | Creates an infinite enumerator from any block, just called over and over. | 
| .product | Generates a new enumerator object that generates a Cartesian product of given enumerable objects. | 
Instance Method Summary
- 
    
      #_enumerable_collect  
    
    Alias for Enumerable#collect. 
- 
    
      #_enumerable_collect_concat  
    
    Alias for Enumerable#collect_concat. 
- 
    
      #_enumerable_drop(n)  ⇒ Array 
    
    Alias for Enumerable#drop. 
- 
    
      #_enumerable_drop_while {|element| ... } ⇒ Array 
    
    Alias for Enumerable#drop_while. 
- 
    
      #_enumerable_filter  
    
    Alias for Enumerable#filter. 
- 
    
      #_enumerable_filter_map {|element| ... } ⇒ Array 
    
    Alias for Enumerable#filter_map. 
- 
    
      #_enumerable_find_all  
    
    Alias for Enumerable#find_all. 
- 
    
      #_enumerable_flat_map {|element| ... } ⇒ Array 
    
    Alias for Enumerable#flat_map. 
- 
    
      #_enumerable_grep(pattern)  ⇒ Array 
    
    Alias for Enumerable#grep. 
- 
    
      #_enumerable_grep_v(pattern)  ⇒ Array 
    
    Alias for Enumerable#grep_v. 
- 
    
      #_enumerable_map {|element| ... } ⇒ Array 
    
    Alias for Enumerable#map. 
- 
    
      #_enumerable_reject {|element| ... } ⇒ Array 
    
    Alias for Enumerable#reject. 
- 
    
      #_enumerable_select {|element| ... } ⇒ Array 
    
    Alias for Enumerable#select. 
- 
    
      #_enumerable_take(n)  ⇒ Array 
    
    Alias for Enumerable#take. 
- 
    
      #_enumerable_take_while {|element| ... } ⇒ Array 
    
    Alias for Enumerable#take_while. 
- 
    
      #_enumerable_uniq  ⇒ Array 
    
    Alias for Enumerable#uniq. 
- 
    
      #_enumerable_zip(*other_enums)  ⇒ Array 
    
    Alias for Enumerable#zip. 
- #chunk(*args) (also: #slice_before, #slice_after, #slice_when, #chunk_while)
- 
    
      #chunk_while(*args)  
    
    Alias for #chunk. 
- #collect
- #collect_concat
- #compact
- #drop(n)
- #drop_while
- 
    
      #eager  ⇒ Enumerator 
    
    Returns a non-lazy ::Enumeratorconverted from the lazy enumerator.
- 
    
      #enum_for(method = :each, *args)  ⇒ Lazy 
    
    Alias for #to_enum. 
- #filter
- #filter_map
- #find_all
- #flat_map
- 
    
      #force  ⇒ Array 
    
    Alias for #to_a. 
- #grep
- #grep_v
- 
    
      #lazy  ⇒ Lazy 
    
    Returns self. 
- #map
- #reject
- #select
- 
    
      #slice_after(*args)  
    
    Alias for #chunk. 
- 
    
      #slice_before(*args)  
    
    Alias for #chunk. 
- 
    
      #slice_when(*args)  
    
    Alias for #chunk. 
- #take(n)
- #take_while
- 
    
      #to_a  ⇒ Array 
      (also: #force)
    
    Expands #lazy enumerator to an array. 
- 
    
      #to_enum(method = :each, *args)  ⇒ Lazy 
      (also: #enum_for)
    
    Similar to Object#to_enum, except it returns a lazy enumerator. 
- #uniq
- #zip
- 
    
      #_enumerable_with_index(offset = 0) {|(*args), idx| ... } 
    
    private
    Alias for #with_index. 
::Enumerator - Inherited
| #+ | Returns an enumerator object generated from this enumerator and a given enumerable. | 
| #each | Iterates over the block according to how this  | 
| #each_with_index | Same as #with_index(0), i.e. there is no starting offset. | 
| #each_with_object | Alias for #with_object. | 
| #feed | Sets the value to be returned by the next yield inside  | 
| #inspect | Creates a printable version of e. | 
| #next | Returns the next object in the enumerator, and move the internal position forward. | 
| #next_values | Returns the next object as an array in the enumerator, and move the internal position forward. | 
| #peek | Returns the next object in the enumerator, but doesn’t move the internal position forward. | 
| #peek_values | Returns the next object as an array, similar to #next_values, but doesn’t move the internal position forward. | 
| #rewind | Rewinds the enumeration sequence to the beginning. | 
| #size | Returns the size of the enumerator, or  | 
| #with_index | Iterates the given block for each element with an index, which starts from  | 
| #with_object | Iterates the given block for each element with an arbitrary object,  | 
| #initialize_copy | |
::Enumerable - Included
| #all? | Returns whether every element meets a given criterion. | 
| #any? | Returns whether any element meets a given criterion. | 
| #chain | Returns an enumerator object generated from this enumerator and given enumerables. | 
| #chunk | Each element in the returned enumerator is a 2-element array consisting of: | 
| #chunk_while | Creates an enumerator for each chunked elements. | 
| #collect | Alias for Enumerable#map. | 
| #collect_concat | Alias for Enumerable#flat_map. | 
| #compact | Returns an array of all non- | 
| #count | Returns the count of elements, based on an argument or block criterion, if given. | 
| #cycle | When called with positive integer argument  | 
| #detect | Alias for Enumerable#find. | 
| #drop | For positive integer  | 
| #drop_while | Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements after that point: | 
| #each_cons | Calls the block with each successive overlapped  | 
| #each_entry | Calls the given block with each element, converting multiple values from yield to an array; returns  | 
| #each_slice | Calls the block with each successive disjoint  | 
| #each_with_index | With a block given, calls the block with each element and its index; returns  | 
| #each_with_object | Calls the block once for each element, passing both the element and the given object: | 
| #entries | Alias for Enumerable#to_a. | 
| #filter | Returns an array containing elements selected by the block. | 
| #filter_map | Returns an array containing truthy elements returned by the block. | 
| #find | Returns the first element for which the block returns a truthy value. | 
| #find_all | Alias for Enumerable#filter. | 
| #find_index | Returns the index of the first element that meets a specified criterion, or  | 
| #first | Returns the first element or elements. | 
| #flat_map | Returns an array of flattened objects returned by the block. | 
| #grep | Returns an array of objects based elements of  | 
| #grep_v | Returns an array of objects based on elements of  | 
| #group_by | With a block given returns a hash: | 
| #include? | Alias for Enumerable#member?. | 
| #inject | Returns an object formed from operands via either: | 
| #lazy | Returns an  | 
| #map | Returns an array of objects returned by the block. | 
| #max | Returns the element with the maximum element according to a given criterion. | 
| #max_by | Returns the elements for which the block returns the maximum values. | 
| #member? | Returns whether for any element  | 
| #min | Returns the element with the minimum element according to a given criterion. | 
| #min_by | Returns the elements for which the block returns the minimum values. | 
| #minmax | Returns a 2-element array containing the minimum and maximum elements according to a given criterion. | 
| #minmax_by | Returns a 2-element array containing the elements for which the block returns minimum and maximum values: | 
| #none? | Returns whether no element meets a given criterion. | 
| #one? | Returns whether exactly one element meets a given criterion. | 
| #partition | With a block given, returns an array of two arrays: | 
| #reduce | Alias for Enumerable#inject. | 
| #reject | Returns an array of objects rejected by the block. | 
| #reverse_each | With a block given, calls the block with each element, but in reverse order; returns  | 
| #select | Alias for Enumerable#filter. | 
| #slice_after | Creates an enumerator for each chunked elements. | 
| #slice_before | With argument  | 
| #slice_when | Creates an enumerator for each chunked elements. | 
| #sort | Returns an array containing the sorted elements of  | 
| #sort_by | With a block given, returns an array of elements of  | 
| #sum | With no block given, returns the sum of  | 
| #take | For non-negative integer  | 
| #take_while | Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements up to that point: | 
| #tally | Returns a hash containing the counts of equal elements: | 
| #to_a | Returns an array containing the items in  | 
| #to_h | When  | 
| #to_set | Makes a set from the enumerable object with given arguments. | 
| #uniq | With no block, returns a new array containing only unique elements; the array has no two elements  | 
| #zip | With no block given, returns a new array  | 
Constructor Details
.new(obj, size = nil) {|yielder, *values| ... }
Creates a new Lazy enumerator. When the enumerator is actually enumerated (e.g. by calling #force), obj will be enumerated and each value passed to the given block. The block can yield values back using yielder. For example, to create a “filter+map” enumerator:
def filter_map(sequence)
  Lazy.new(sequence) do |yielder, *values|
    result = yield *values
    yielder << result if result
  end
end
filter_map(1..Float::INFINITY) {|i| i*i if i.even?}.first(5)
#=> [4, 16, 36, 64, 100]# File 'enumerator.c', line 1833
static VALUE
lazy_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE obj, size = Qnil;
    VALUE generator;
    rb_check_arity(argc, 1, 2);
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy new without a block");
    }
    obj = argv[0];
    if (argc > 1) {
        size = argv[1];
    }
    generator = generator_allocate(rb_cGenerator);
    rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
    enumerator_init(self, generator, sym_each, 0, 0, 0, size, 0);
    rb_ivar_set(self, id_receiver, obj);
    return self;
}
  Instance Method Details
#_enumerable_collect
Alias for Enumerable#collect.
#_enumerable_collect_concat
Alias for Enumerable#collect_concat.
#_enumerable_drop(n) ⇒ Array
Alias for Enumerable#drop.
    
      #_enumerable_drop_while {|element| ... } ⇒ Array 
      #_enumerable_drop_while  ⇒ Enumerator 
    
  
Alias for Enumerable#drop_while.
#_enumerable_filter
Alias for Enumerable#filter.
    
      #_enumerable_filter_map {|element| ... } ⇒ Array 
      #_enumerable_filter_map  ⇒ Enumerator 
    
  
Alias for Enumerable#filter_map.
#_enumerable_find_all
Alias for Enumerable#find_all.
    
      #_enumerable_flat_map {|element| ... } ⇒ Array 
      #_enumerable_flat_map  ⇒ Enumerator 
    
  
Alias for Enumerable#flat_map.
Alias for Enumerable#grep.
Alias for Enumerable#grep_v.
    
      #_enumerable_map {|element| ... } ⇒ Array 
      #_enumerable_map  ⇒ Enumerator 
    
  
Alias for Enumerable#map.
    
      #_enumerable_reject {|element| ... } ⇒ Array 
      #_enumerable_reject  ⇒ Enumerator 
    
  
Alias for Enumerable#reject.
    
      #_enumerable_select {|element| ... } ⇒ Array 
      #_enumerable_select  ⇒ Enumerator 
    
  
Alias for Enumerable#select.
#_enumerable_take(n) ⇒ Array
Alias for Enumerable#take.
    
      #_enumerable_take_while {|element| ... } ⇒ Array 
      #_enumerable_take_while  ⇒ Enumerator 
    
  
Alias for Enumerable#take_while.
Alias for Enumerable#uniq.
    
      #_enumerable_with_index(offset = 0) {|(*args), idx| ... }  (private)
      #_enumerable_with_index(offset = 0)  
    
  
Alias for Enumerator#with_index.
    
      #_enumerable_zip(*other_enums)  ⇒ Array 
      #_enumerable_zip(*other_enums) {|array| ... } ⇒ nil 
    
  
nil 
    Alias for Enumerable#zip.
#chunk(*args) Also known as: #slice_before, #slice_after, #slice_when, #chunk_while
[ GitHub ]# File 'enumerator.c', line 2870
static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}
  #chunk_while(*args)
Alias for #chunk.
#collect
[ GitHub ]#collect_concat
[ GitHub ]#compact
[ GitHub ]# File 'enumerator.c', line 2740
static VALUE
lazy_compact(VALUE obj)
{
    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_compact_funcs);
}
  #drop(n)
[ GitHub ]# File 'enumerator.c', line 2615
static VALUE
lazy_drop(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    VALUE argv[2];
    argv[0] = sym_each;
    argv[1] = n;
    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }
    return lazy_add_method(obj, 2, argv, n, rb_ary_new3(1, n), &lazy_drop_funcs);
}
  #drop_while
[ GitHub ]#eager ⇒ Enumerator
Returns a non-lazy ::Enumerator converted from the lazy enumerator.
# File 'enumerator.c', line 2035
static VALUE
lazy_eager(VALUE self)
{
    return enumerator_init(enumerator_allocate(rb_cEnumerator),
                           self, sym_each, 0, 0, lazy_eager_size, Qnil, 0);
}
  
    
      #to_enum(method = :each, *args)  ⇒ Lazy 
      #enum_for(method = :each, *args)  ⇒ Lazy 
      #to_enum(method = :each, *args) {|*args| ... } ⇒ Lazy 
      #enum_for(method = :each, *args) {|*args| ... } ⇒ Lazy 
    
  
Lazy 
      #enum_for(method = :each, *args)  ⇒ Lazy 
      #to_enum(method = :each, *args) {|*args| ... } ⇒ Lazy 
      #enum_for(method = :each, *args) {|*args| ... } ⇒ Lazy 
    Alias for #to_enum.
#filter
[ GitHub ]#filter_map
[ GitHub ]#find_all
[ GitHub ]#flat_map
[ GitHub ]Alias for #to_a.
#grep
[ GitHub ]#grep_v
[ GitHub ]
    #lazy  ⇒ Lazy   
Returns self.
# File 'enumerator.c', line 2883
static VALUE
lazy_lazy(VALUE obj)
{
    return obj;
}
  #map
[ GitHub ]#reject
[ GitHub ]#select
[ GitHub ]#slice_after(*args)
Alias for #chunk.
#slice_before(*args)
Alias for #chunk.
#slice_when(*args)
Alias for #chunk.
#take(n)
[ GitHub ]# File 'enumerator.c', line 2525
static VALUE
lazy_take(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }
    n = LONG2NUM(len);          /* no more conversion */
    return lazy_add_method(obj, 0, 0, n, rb_ary_new3(1, n), &lazy_take_funcs);
}
  #take_while
[ GitHub ]Also known as: #force
Expands #lazy enumerator to an array. See Enumerable#to_a.
# File 'enumerator.c', line 1864
static VALUE
lazy_to_a(VALUE self)
{
}
  
    
      #to_enum(method = :each, *args)  ⇒ Lazy 
      #enum_for(method = :each, *args)  ⇒ Lazy 
      #to_enum(method = :each, *args) {|*args| ... } ⇒ Lazy 
      #enum_for(method = :each, *args) {|*args| ... } ⇒ Lazy 
    
    Also known as: #enum_for
  
Lazy 
      #enum_for(method = :each, *args)  ⇒ Lazy 
      #to_enum(method = :each, *args) {|*args| ... } ⇒ Lazy 
      #enum_for(method = :each, *args) {|*args| ... } ⇒ Lazy 
    Similar to Object#to_enum, except it returns a lazy enumerator. This makes it easy to define ::Enumerable methods that will naturally remain lazy if called from a lazy enumerator.
For example, continuing from the example in Object#to_enum:
# See Object#to_enum for the definition of repeat
r = 1..Float::INFINITY
r.repeat(2).first(5) # => [1, 1, 2, 2, 3]
r.repeat(2).class # => Enumerator
r.repeat(2).map{|n| n ** 2}.first(5) # => endless loop!
# works naturally on lazy enumerator:
r.lazy.repeat(2).class # => Enumerator::Lazy
r.lazy.repeat(2).map{|n| n ** 2}.first(5) # => [1, 1, 4, 4, 9]# File 'enumerator.c', line 2003
static VALUE
lazy_to_enum(int argc, VALUE *argv, VALUE self)
{
    VALUE lazy, meth = sym_each, super_meth;
    if (argc > 0) {
        --argc;
        meth = *argv++;
    }
    if (RTEST((super_meth = rb_hash_aref(lazy_use_super_method, meth)))) {
        meth = super_meth;
    }
    lazy = lazy_to_enum_i(self, meth, argc, argv, 0, rb_keyword_given_p());
    if (rb_block_given_p()) {
        enumerator_ptr(lazy)->size = rb_block_proc();
    }
    return lazy;
}