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)

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
# File 'enumerator.c', line 1764

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)

653
654
655
656
657
658
659
660
661
662
# File 'enumerator.c', line 653

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)

2768
2769
2770
2771
2772
# File 'enumerator.c', line 2768

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)

2768
2769
2770
2771
2772
# File 'enumerator.c', line 2768

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)

2025
2026
2027
2028
2029
2030
2031
2032
2033
# File 'enumerator.c', line 2025

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)

2110
2111
2112
2113
2114
2115
2116
2117
2118
# File 'enumerator.c', line 2110

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);
}

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

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


2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
# File 'enumerator.c', line 2549

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)

2593
2594
2595
2596
2597
2598
2599
2600
2601
# File 'enumerator.c', line 2593

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:


1965
1966
1967
1968
1969
1970
# File 'enumerator.c', line 1965

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)

1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
# File 'enumerator.c', line 1933

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;
}

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

2140
2141
2142
2143
2144
2145
2146
2147
2148
# File 'enumerator.c', line 2140

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)

2174
2175
2176
2177
2178
2179
2180
2181
2182
# File 'enumerator.c', line 2174

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)

2140
2141
2142
2143
2144
2145
2146
2147
2148
# File 'enumerator.c', line 2140

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)

2110
2111
2112
2113
2114
2115
2116
2117
2118
# File 'enumerator.c', line 2110

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)

2252
2253
2254
2255
2256
2257
2258
# File 'enumerator.c', line 2252

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)

2299
2300
2301
2302
2303
2304
2305
# File 'enumerator.c', line 2299

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.


2781
2782
2783
2784
2785
# File 'enumerator.c', line 2781

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)

2025
2026
2027
2028
2029
2030
2031
2032
2033
# File 'enumerator.c', line 2025

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)

2203
2204
2205
2206
2207
2208
2209
2210
2211
# File 'enumerator.c', line 2203

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)

2140
2141
2142
2143
2144
2145
2146
2147
2148
# File 'enumerator.c', line 2140

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)

2768
2769
2770
2771
2772
# File 'enumerator.c', line 2768

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)

2768
2769
2770
2771
2772
# File 'enumerator.c', line 2768

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)

2768
2769
2770
2771
2772
# File 'enumerator.c', line 2768

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.


2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
# File 'enumerator.c', line 2453

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)

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

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:


1795
1796
1797
# File 'enumerator.c', line 1795

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)

1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
# File 'enumerator.c', line 1933

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;
}

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

2648
2649
2650
2651
2652
2653
2654
# File 'enumerator.c', line 2648

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)

2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
# File 'enumerator.c', line 2701

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)

2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
# File 'enumerator.c', line 2380

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);
}