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]
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
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.
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.
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
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 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}]
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.
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);
}
|
#eager ⇒ Enumerator
Returns a non-lazy Enumerator converted from the lazy enumerator.
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]
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.
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]
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.
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 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}]
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.
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.
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);
}
|
#lazy ⇒ Object
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
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.
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.
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.
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.
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.
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.
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_a ⇒ Array #force ⇒ Array Also known as: force
Expands lazy
enumerator to an array. See Enumerable#to_a.
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]
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;
}
|
#uniq ⇒ Object #uniq {|item| ... } ⇒ Object Also known as: _enumerable_uniq
Like Enumerable#uniq, but chains operation to be lazy-evaluated.
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.
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.
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);
}
|