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
666 667 668 669 670 671 672 673 674 675 |
# File 'enumerator.c', line 666
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.
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.
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
2023 2024 2025 2026 2027 2028 2029 2030 2031 |
# File 'enumerator.c', line 2023
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}]
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 |
# File 'enumerator.c', line 2108
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.
2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 |
# File 'enumerator.c', line 2550
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.
2594 2595 2596 2597 2598 2599 2600 2601 2602 |
# File 'enumerator.c', line 2594
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.
1963 1964 1965 1966 1967 1968 |
# File 'enumerator.c', line 1963
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]
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 |
# File 'enumerator.c', line 1931
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.
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}]
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 |
# File 'enumerator.c', line 2108
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.
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.
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
2023 2024 2025 2026 2027 2028 2029 2030 2031 |
# File 'enumerator.c', line 2023
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.
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.
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.
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.
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 |
# File 'enumerator.c', line 2454
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.
2496 2497 2498 2499 2500 2501 2502 2503 2504 |
# File 'enumerator.c', line 2496
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]
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 |
# File 'enumerator.c', line 1931
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.
2649 2650 2651 2652 2653 2654 2655 |
# File 'enumerator.c', line 2649
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.
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.
2379 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 2410 |
# File 'enumerator.c', line 2379
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);
}
|