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(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(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, #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)


1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
# File 'enumerator.c', line 1756

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)


658
659
660
661
662
663
664
665
666
667
# File 'enumerator.c', line 658

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)


2760
2761
2762
2763
2764
# File 'enumerator.c', line 2760

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)


2760
2761
2762
2763
2764
# File 'enumerator.c', line 2760

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)


2015
2016
2017
2018
2019
2020
2021
2022
2023
# File 'enumerator.c', line 2015

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)


2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
# File 'enumerator.c', line 2100

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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
					 lazy_flat_map_proc, 0),
			   Qnil, 0);
}

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

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



2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
# File 'enumerator.c', line 2542

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)


2586
2587
2588
2589
2590
2591
2592
2593
2594
# File 'enumerator.c', line 2586

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:



1955
1956
1957
1958
1959
1960
# File 'enumerator.c', line 1955

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)


1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
# File 'enumerator.c', line 1923

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, PASS_KW_SPLAT);
    if (rb_block_given_p()) {
	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)


2132
2133
2134
2135
2136
2137
2138
2139
2140
# File 'enumerator.c', line 2132

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)


2166
2167
2168
2169
2170
2171
2172
2173
2174
# File 'enumerator.c', line 2166

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)


2132
2133
2134
2135
2136
2137
2138
2139
2140
# File 'enumerator.c', line 2132

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)


2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
# File 'enumerator.c', line 2100

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_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
					 lazy_flat_map_proc, 0),
			   Qnil, 0);
}

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


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

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)


2291
2292
2293
2294
2295
2296
2297
# File 'enumerator.c', line 2291

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.



2773
2774
2775
2776
2777
# File 'enumerator.c', line 2773

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)


2015
2016
2017
2018
2019
2020
2021
2022
2023
# File 'enumerator.c', line 2015

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)


2195
2196
2197
2198
2199
2200
2201
2202
2203
# File 'enumerator.c', line 2195

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)


2132
2133
2134
2135
2136
2137
2138
2139
2140
# File 'enumerator.c', line 2132

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)


2760
2761
2762
2763
2764
# File 'enumerator.c', line 2760

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)


2760
2761
2762
2763
2764
# File 'enumerator.c', line 2760

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)


2760
2761
2762
2763
2764
# File 'enumerator.c', line 2760

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.



2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
# File 'enumerator.c', line 2446

static VALUE
lazy_take(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    int argc = 0;
    VALUE argv[2];

    if (len < 0) {
	rb_raise(rb_eArgError, "attempt to take negative size");
    }

    if (len == 0) {
       argv[0] = sym_cycle;
       argv[1] = INT2NUM(0);
       argc = 2;
    }

    return lazy_add_method(obj, argc, argv, 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)


2488
2489
2490
2491
2492
2493
2494
2495
2496
# File 'enumerator.c', line 2488

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:



1787
1788
1789
# File 'enumerator.c', line 1787

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)


1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
# File 'enumerator.c', line 1923

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, PASS_KW_SPLAT);
    if (rb_block_given_p()) {
	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)


2641
2642
2643
2644
2645
2646
2647
# File 'enumerator.c', line 2641

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, iterates 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)


2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
# File 'enumerator.c', line 2693

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)


2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
# File 'enumerator.c', line 2371

static VALUE
lazy_zip(int argc, VALUE *argv, VALUE obj)
{
    VALUE ary, v;
    long i;
    rb_block_call_func *func = lazy_zip_arrays_func;

    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);
	    func = lazy_zip_func;
	    break;
	}
	rb_ary_push(ary, v);
    }

    return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
					 func, ary),
			   ary, lazy_receiver_size);
}