Class: Enumerator::Lazy

Inherits:
Enumerator show all
Defined in:
enumerator.c,
enumerator.c

Overview

Enumerator::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.

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 Enumerator::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 block

This 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)

Instance Method Summary collapse

Methods inherited from Enumerator

#+, #each, #each_with_index, #each_with_object, #feed, #initialize_copy, #inspect, #next, #next_values, #peek, #peek_values, produce, product, #rewind, #size, #with_object

Methods included from Enumerable

#all?, #any?, #chain, #count, #cycle, #detect, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #find, #find_index, #first, #group_by, #include?, #inject, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reverse_each, #sort, #sort_by, #sum, #tally, #to_h

Constructor Details

#new(obj, size = nil) {|yielder, *values| ... } ⇒ Object

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]

Yields:

  • (yielder, *values)


1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
# File 'enumerator.c', line 1802

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

#with_index(offset = 0) {|(*args), idx| ... } ⇒ Object (private) #with_index(offset = 0) ⇒ Object (private)

Iterates the given block for each element with an index, which starts from offset. If no block is given, returns a new Enumerator that includes the index, starting from offset

offset

the starting index to use

Overloads:

  • #with_index(offset = 0) {|(*args), idx| ... } ⇒ Object

    Yields:

    • ((*args), idx)


674
675
676
677
678
679
680
681
682
683
# File 'enumerator.c', line 674

static VALUE
enumerator_with_index(int argc, VALUE *argv, VALUE obj)
{
    VALUE memo;

    rb_check_arity(argc, 0, 1);
    RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_enum_size);
    memo = (!argc || NIL_P(memo = argv[0])) ? INT2FIX(0) : rb_to_int(memo);
    return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)MEMO_NEW(memo, 0, 0));
}

#chunk {|elt| ... } ⇒ Object

Like Enumerable#chunk, but chains operation to be lazy-evaluated.

Yields:

  • (elt)


2839
2840
2841
2842
2843
# File 'enumerator.c', line 2839

static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}

#chunk_while {|elt_before, elt_after| ... } ⇒ Object

Like Enumerable#chunk_while, but chains operation to be lazy-evaluated.

Yields:

  • (elt_before, elt_after)


2839
2840
2841
2842
2843
# File 'enumerator.c', line 2839

static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}

#collect {|obj| ... } ⇒ Object #map {|obj| ... } ⇒ Object Also known as: _enumerable_collect

Like Enumerable#map, but chains operation to be lazy-evaluated.

(1..Float::INFINITY).lazy.map {|i| i**2 }
#=> #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:map>
(1..Float::INFINITY).lazy.map {|i| i**2 }.first(3)
#=> [1, 4, 9]

Overloads:

  • #collect {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #map {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2066
2067
2068
2069
2070
2071
2072
2073
2074
# File 'enumerator.c', line 2066

static VALUE
lazy_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy map without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs);
}

#collect_concat {|obj| ... } ⇒ Object #flat_map {|obj| ... } ⇒ Object Also known as: _enumerable_collect_concat

Returns a new lazy enumerator with the concatenated results of running block once for every element in the lazy enumerator.

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

A value x returned by block is decomposed if either of the following conditions is true:

  • x responds to both each and force, which means that x is a lazy enumerator.

  • x is an array or responds to to_ary.

Otherwise, x is contained as-is in the return value.

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force
#=> [{:a=>1}, {:b=>2}]

Overloads:

  • #collect_concat {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #flat_map {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2151
2152
2153
2154
2155
2156
2157
2158
2159
# File 'enumerator.c', line 2151

static VALUE
lazy_flat_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs);
}

#compactObject

Like Enumerable#compact, but chains operation to be lazy-evaluated.



2709
2710
2711
2712
2713
# File 'enumerator.c', line 2709

static VALUE
lazy_compact(VALUE obj)
{
    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_compact_funcs);
}

#drop(n) ⇒ Object Also known as: _enumerable_drop

Like Enumerable#drop, but chains operation to be lazy-evaluated.



2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
# File 'enumerator.c', line 2584

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 {|obj| ... } ⇒ Object Also known as: _enumerable_drop_while

Like Enumerable#drop_while, but chains operation to be lazy-evaluated.

Yields:

  • (obj)


2628
2629
2630
2631
2632
2633
2634
2635
2636
# File 'enumerator.c', line 2628

static VALUE
lazy_drop_while(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
    }

    return lazy_add_method(obj, 0, 0, Qfalse, Qnil, &lazy_drop_while_funcs);
}

#eagerEnumerator

Returns a non-lazy Enumerator converted from the lazy enumerator.

Returns:



2006
2007
2008
2009
2010
2011
# File 'enumerator.c', line 2006

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) ⇒ Object #enum_for(method = :each, *args) ⇒ Object #to_enum(method = :each, *args) {|*args| ... } ⇒ Object #enum_for(method = :each, *args) {|*args| ... } ⇒ Object

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]

Overloads:

  • #to_enum(method = :each, *args) {|*args| ... } ⇒ Object

    Yields:

    • (*args)
  • #enum_for(method = :each, *args) {|*args| ... } ⇒ Object

    Yields:

    • (*args)


1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
# File 'enumerator.c', line 1974

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()) {
        RB_OBJ_WRITE(lazy, &enumerator_ptr(lazy)->size, rb_block_proc());
    }
    return lazy;
}

#find_all {|obj| ... } ⇒ Object #select {|obj| ... } ⇒ Object #filter {|obj| ... } ⇒ Object Also known as: _enumerable_filter

Like Enumerable#select, but chains operation to be lazy-evaluated.

Overloads:

  • #find_all {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #select {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #filter {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2181
2182
2183
2184
2185
2186
2187
2188
2189
# File 'enumerator.c', line 2181

static VALUE
lazy_select(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy select without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs);
}

#filter_map {|obj| ... } ⇒ Object Also known as: _enumerable_filter_map

Like Enumerable#filter_map, but chains operation to be lazy-evaluated.

(1..).lazy.filter_map { |i| i * 2 if i.even? }.first(5)
#=> [4, 8, 12, 16, 20]

Yields:

  • (obj)


2215
2216
2217
2218
2219
2220
2221
2222
2223
# File 'enumerator.c', line 2215

static VALUE
lazy_filter_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy filter_map without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_filter_map_funcs);
}

#find_all {|obj| ... } ⇒ Object #select {|obj| ... } ⇒ Object #filter {|obj| ... } ⇒ Object Also known as: _enumerable_find_all

Like Enumerable#select, but chains operation to be lazy-evaluated.

Overloads:

  • #find_all {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #select {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #filter {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2181
2182
2183
2184
2185
2186
2187
2188
2189
# File 'enumerator.c', line 2181

static VALUE
lazy_select(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy select without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs);
}

#collect_concat {|obj| ... } ⇒ Object #flat_map {|obj| ... } ⇒ Object Also known as: _enumerable_flat_map

Returns a new lazy enumerator with the concatenated results of running block once for every element in the lazy enumerator.

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

A value x returned by block is decomposed if either of the following conditions is true:

  • x responds to both each and force, which means that x is a lazy enumerator.

  • x is an array or responds to to_ary.

Otherwise, x is contained as-is in the return value.

[{a:1}, {b:2}].lazy.flat_map {|i| i}.force
#=> [{:a=>1}, {:b=>2}]

Overloads:

  • #collect_concat {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #flat_map {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2151
2152
2153
2154
2155
2156
2157
2158
2159
# File 'enumerator.c', line 2151

static VALUE
lazy_flat_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs);
}

#grep(pattern) ⇒ Object #grep(pattern) {|obj| ... } ⇒ Object Also known as: _enumerable_grep

Like Enumerable#grep, but chains operation to be lazy-evaluated.

Overloads:

  • #grep(pattern) {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2293
2294
2295
2296
2297
2298
2299
# File 'enumerator.c', line 2293

static VALUE
lazy_grep(VALUE obj, VALUE pattern)
{
    const lazyenum_funcs *const funcs = rb_block_given_p() ?
        &lazy_grep_iter_funcs : &lazy_grep_funcs;
    return lazy_add_method(obj, 0, 0, pattern, rb_ary_new3(1, pattern), funcs);
}

#grep_v(pattern) ⇒ Object #grep_v(pattern) {|obj| ... } ⇒ Object Also known as: _enumerable_grep_v

Like Enumerable#grep_v, but chains operation to be lazy-evaluated.

Overloads:

  • #grep_v(pattern) {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2340
2341
2342
2343
2344
2345
2346
# File 'enumerator.c', line 2340

static VALUE
lazy_grep_v(VALUE obj, VALUE pattern)
{
    const lazyenum_funcs *const funcs = rb_block_given_p() ?
        &lazy_grep_v_iter_funcs : &lazy_grep_v_funcs;
    return lazy_add_method(obj, 0, 0, pattern, rb_ary_new3(1, pattern), funcs);
}

#lazyObject

Returns self.



2852
2853
2854
2855
2856
# File 'enumerator.c', line 2852

static VALUE
lazy_lazy(VALUE obj)
{
    return obj;
}

#collect {|obj| ... } ⇒ Object #map {|obj| ... } ⇒ Object Also known as: _enumerable_map

Like Enumerable#map, but chains operation to be lazy-evaluated.

(1..Float::INFINITY).lazy.map {|i| i**2 }
#=> #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:map>
(1..Float::INFINITY).lazy.map {|i| i**2 }.first(3)
#=> [1, 4, 9]

Overloads:

  • #collect {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #map {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2066
2067
2068
2069
2070
2071
2072
2073
2074
# File 'enumerator.c', line 2066

static VALUE
lazy_map(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy map without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs);
}

#reject {|obj| ... } ⇒ Object Also known as: _enumerable_reject

Like Enumerable#reject, but chains operation to be lazy-evaluated.

Yields:

  • (obj)


2244
2245
2246
2247
2248
2249
2250
2251
2252
# File 'enumerator.c', line 2244

static VALUE
lazy_reject(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy reject without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_reject_funcs);
}

#find_all {|obj| ... } ⇒ Object #select {|obj| ... } ⇒ Object #filter {|obj| ... } ⇒ Object Also known as: _enumerable_select

Like Enumerable#select, but chains operation to be lazy-evaluated.

Overloads:

  • #find_all {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #select {|obj| ... } ⇒ Object

    Yields:

    • (obj)
  • #filter {|obj| ... } ⇒ Object

    Yields:

    • (obj)


2181
2182
2183
2184
2185
2186
2187
2188
2189
# File 'enumerator.c', line 2181

static VALUE
lazy_select(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy select without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs);
}

#slice_after(pattern) ⇒ Object #slice_after {|elt| ... } ⇒ Object

Like Enumerable#slice_after, but chains operation to be lazy-evaluated.

Overloads:

  • #slice_after {|elt| ... } ⇒ Object

    Yields:

    • (elt)


2839
2840
2841
2842
2843
# File 'enumerator.c', line 2839

static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}

#slice_before(pattern) ⇒ Object #slice_before {|elt| ... } ⇒ Object

Like Enumerable#slice_before, but chains operation to be lazy-evaluated.

Overloads:

  • #slice_before {|elt| ... } ⇒ Object

    Yields:

    • (elt)


2839
2840
2841
2842
2843
# File 'enumerator.c', line 2839

static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}

#slice_when {|elt_before, elt_after| ... } ⇒ Object

Like Enumerable#slice_when, but chains operation to be lazy-evaluated.

Yields:

  • (elt_before, elt_after)


2839
2840
2841
2842
2843
# File 'enumerator.c', line 2839

static VALUE
lazy_super(int argc, VALUE *argv, VALUE lazy)
{
    return enumerable_lazy(rb_call_super(argc, argv));
}

#take(n) ⇒ Object Also known as: _enumerable_take

Like Enumerable#take, but chains operation to be lazy-evaluated.



2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
# File 'enumerator.c', line 2494

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 {|obj| ... } ⇒ Object Also known as: _enumerable_take_while

Like Enumerable#take_while, but chains operation to be lazy-evaluated.

Yields:

  • (obj)


2530
2531
2532
2533
2534
2535
2536
2537
2538
# File 'enumerator.c', line 2530

static VALUE
lazy_take_while(VALUE obj)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
    }

    return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_take_while_funcs);
}

#to_aArray #forceArray Also known as: force

Expands lazy enumerator to an array. See Enumerable#to_a.

Overloads:



1833
1834
1835
1836
# File 'enumerator.c', line 1833

static VALUE
lazy_to_a(VALUE self)
{
}

#to_enum(method = :each, *args) ⇒ Object #enum_for(method = :each, *args) ⇒ Object #to_enum(method = :each, *args) {|*args| ... } ⇒ Object #enum_for(method = :each, *args) {|*args| ... } ⇒ Object

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]

Overloads:

  • #to_enum(method = :each, *args) {|*args| ... } ⇒ Object

    Yields:

    • (*args)
  • #enum_for(method = :each, *args) {|*args| ... } ⇒ Object

    Yields:

    • (*args)


1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
# File 'enumerator.c', line 1974

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()) {
        RB_OBJ_WRITE(lazy, &enumerator_ptr(lazy)->size, rb_block_proc());
    }
    return lazy;
}

#uniqObject #uniq {|item| ... } ⇒ Object Also known as: _enumerable_uniq

Like Enumerable#uniq, but chains operation to be lazy-evaluated.

Overloads:

  • #uniq {|item| ... } ⇒ Object

    Yields:

    • (item)


2683
2684
2685
2686
2687
2688
2689
# File 'enumerator.c', line 2683

static VALUE
lazy_uniq(VALUE obj)
{
    const lazyenum_funcs *const funcs =
        rb_block_given_p() ? &lazy_uniq_iter_funcs : &lazy_uniq_funcs;
    return lazy_add_method(obj, 0, 0, Qnil, Qnil, funcs);
}

#with_index(offset = 0) {|(*args), idx| ... } ⇒ Object #with_index(offset = 0) ⇒ Object

If a block is given, returns a lazy enumerator that will iterate over the given block for each element with an index, which starts from offset, and returns a lazy enumerator that yields the same values (without the index).

If a block is not given, returns a new lazy enumerator that includes the index, starting from offset.

offset

the starting index to use

See Enumerator#with_index.

Overloads:

  • #with_index(offset = 0) {|(*args), idx| ... } ⇒ Object

    Yields:

    • ((*args), idx)


2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
# File 'enumerator.c', line 2767

static VALUE
lazy_with_index(int argc, VALUE *argv, VALUE obj)
{
    VALUE memo;

    rb_scan_args(argc, argv, "01", &memo);
    if (NIL_P(memo))
        memo = LONG2NUM(0);

    return lazy_add_method(obj, 0, 0, memo, rb_ary_new_from_values(1, &memo), &lazy_with_index_funcs);
}

#zip(arg, ...) ⇒ Object #zip(arg, ...) {|arr| ... } ⇒ nil Also known as: _enumerable_zip

Like Enumerable#zip, but chains operation to be lazy-evaluated. However, if a block is given to zip, values are enumerated immediately.

Overloads:

  • #zip(arg, ...) {|arr| ... } ⇒ nil

    Yields:

    • (arr)

    Returns:

    • (nil)


2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
# File 'enumerator.c', line 2419

static VALUE
lazy_zip(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary, v;
    long i;
    const lazyenum_funcs *funcs = &lazy_zip_funcs[1];

    if (rb_block_given_p()) {
        return rb_call_super(argc, argv);
    }

    ary = rb_ary_new2(argc);
    for (i = 0; i < argc; i++) {
        v = rb_check_array_type(argv[i]);
        if (NIL_P(v)) {
            for (; i < argc; i++) {
                if (!rb_respond_to(argv[i], id_each)) {
                    rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
                             rb_obj_class(argv[i]));
                }
            }
            ary = rb_ary_new4(argc, argv);
            funcs = &lazy_zip_funcs[0];
            break;
        }
        rb_ary_push(ary, v);
    }

    return lazy_add_method(obj, 0, 0, ary, ary, funcs);
}