Class: Enumerator::Lazy
- Inherits:
-
Enumerator
- Object
- Enumerator
- Enumerator::Lazy
- 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
-
#_enumerable_with_index(*args) ⇒ Object
private
Iterates the given block for each element with an index, which starts from
offset
. -
#chunk {|elt| ... } ⇒ Object
Like Enumerable#chunk, but chains operation to be lazy-evaluated.
-
#chunk_while {|elt_before, elt_after| ... } ⇒ Object
Like Enumerable#chunk_while, but chains operation to be lazy-evaluated.
-
#collect ⇒ Object
(also: #_enumerable_collect)
Like Enumerable#map, but chains operation to be lazy-evaluated.
-
#collect_concat ⇒ Object
(also: #_enumerable_collect_concat)
Returns a new lazy enumerator with the concatenated results of running
block
once for every element in the lazy enumerator. -
#drop(n) ⇒ Object
(also: #_enumerable_drop)
Like Enumerable#drop, but chains operation to be lazy-evaluated.
-
#drop_while {|obj| ... } ⇒ Object
(also: #_enumerable_drop_while)
Like Enumerable#drop_while, but chains operation to be lazy-evaluated.
-
#eager ⇒ Enumerator
Returns a non-lazy Enumerator converted from the lazy enumerator.
-
#enum_for(*args) ⇒ Object
Similar to Object#to_enum, except it returns a lazy enumerator.
-
#filter ⇒ Object
(also: #_enumerable_filter)
Like Enumerable#select, but chains operation to be lazy-evaluated.
-
#filter_map {|obj| ... } ⇒ Object
(also: #_enumerable_filter_map)
Like Enumerable#filter_map, but chains operation to be lazy-evaluated.
-
#find_all ⇒ Object
(also: #_enumerable_find_all)
Like Enumerable#select, but chains operation to be lazy-evaluated.
-
#flat_map ⇒ Object
(also: #_enumerable_flat_map)
Returns a new lazy enumerator with the concatenated results of running
block
once for every element in the lazy enumerator. -
#grep(pattern) ⇒ Object
(also: #_enumerable_grep)
Like Enumerable#grep, but chains operation to be lazy-evaluated.
-
#grep_v(pattern) ⇒ Object
(also: #_enumerable_grep_v)
Like Enumerable#grep_v, but chains operation to be lazy-evaluated.
-
#new(obj, size = nil) {|yielder, *values| ... } ⇒ Object
constructor
Creates a new Lazy enumerator.
-
#lazy ⇒ Object
Returns self.
-
#map ⇒ Object
(also: #_enumerable_map)
Like Enumerable#map, but chains operation to be lazy-evaluated.
-
#reject {|obj| ... } ⇒ Object
(also: #_enumerable_reject)
Like Enumerable#reject, but chains operation to be lazy-evaluated.
-
#select ⇒ Object
(also: #_enumerable_select)
Like Enumerable#select, but chains operation to be lazy-evaluated.
-
#slice_after ⇒ Object
Like Enumerable#slice_after, but chains operation to be lazy-evaluated.
-
#slice_before ⇒ Object
Like Enumerable#slice_before, but chains operation to be lazy-evaluated.
-
#slice_when {|elt_before, elt_after| ... } ⇒ Object
Like Enumerable#slice_when, but chains operation to be lazy-evaluated.
-
#take(n) ⇒ Object
(also: #_enumerable_take)
Like Enumerable#take, but chains operation to be lazy-evaluated.
-
#take_while {|obj| ... } ⇒ Object
(also: #_enumerable_take_while)
Like Enumerable#take_while, but chains operation to be lazy-evaluated.
-
#to_a ⇒ Object
(also: #force)
Expands
lazy
enumerator to an array. -
#to_enum(*args) ⇒ Object
Similar to Object#to_enum, except it returns a lazy enumerator.
-
#uniq ⇒ Object
(also: #_enumerable_uniq)
Like Enumerable#uniq, but chains operation to be lazy-evaluated.
-
#with_index(*args) ⇒ 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). -
#zip(*args) ⇒ Object
(also: #_enumerable_zip)
Like Enumerable#zip, but chains operation to be lazy-evaluated.
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]
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
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.
2773 2774 2775 2776 2777 |
# File 'enumerator.c', line 2773
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.
2773 2774 2775 2776 2777 |
# File 'enumerator.c', line 2773
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
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 thatx
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}]
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.
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);
}
|
#eager ⇒ Enumerator
Returns a non-lazy Enumerator converted from the lazy enumerator.
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]
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.
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]
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.
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 thatx
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}]
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.
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.
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);
}
|
#lazy ⇒ Object
Returns self.
2786 2787 2788 2789 2790 |
# File 'enumerator.c', line 2786
static VALUE
lazy_lazy(VALUE obj)
{
return obj;
}
|
#collect {|obj| ... } ⇒ Object #map {|obj| ... } ⇒ Object Also known as: _enumerable_map
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.
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.
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.
2773 2774 2775 2776 2777 |
# File 'enumerator.c', line 2773
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.
2773 2774 2775 2776 2777 |
# File 'enumerator.c', line 2773
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.
2773 2774 2775 2776 2777 |
# File 'enumerator.c', line 2773
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.
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_a ⇒ Array #force ⇒ Array Also known as: force
Expands lazy
enumerator to an array. See Enumerable#to_a.
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]
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;
}
|
#uniq ⇒ Object #uniq {|item| ... } ⇒ Object Also known as: _enumerable_uniq
Like Enumerable#uniq, but chains operation to be lazy-evaluated.
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.
2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 |
# File 'enumerator.c', line 2706
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.
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);
}
|