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(URI.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(URI.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. -
#compact ⇒ Object
Like Enumerable#compact, but chains operation to be lazy-evaluated.
-
#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, returns a lazy enumerator that will iterate over 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, product, #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]
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 |
# File 'enumerator.c', line 1802 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
674 675 676 677 678 679 680 681 682 683 |
# File 'enumerator.c', line 674 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.
2839 2840 2841 2842 2843 |
# File 'enumerator.c', line 2839 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.
2839 2840 2841 2842 2843 |
# File 'enumerator.c', line 2839 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]
2066 2067 2068 2069 2070 2071 2072 2073 2074 |
# File 'enumerator.c', line 2066 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}]
2151 2152 2153 2154 2155 2156 2157 2158 2159 |
# File 'enumerator.c', line 2151 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); } |
#compact ⇒ Object
Like Enumerable#compact, but chains operation to be lazy-evaluated.
2709 2710 2711 2712 2713 |
# File 'enumerator.c', line 2709 static VALUE lazy_compact(VALUE obj) { return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_compact_funcs); } |
#drop(n) ⇒ Object Also known as: _enumerable_drop
Like Enumerable#drop, but chains operation to be lazy-evaluated.
2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 |
# File 'enumerator.c', line 2584 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.
2628 2629 2630 2631 2632 2633 2634 2635 2636 |
# File 'enumerator.c', line 2628 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.
2006 2007 2008 2009 2010 2011 |
# File 'enumerator.c', line 2006 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]
1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 |
# File 'enumerator.c', line 1974 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()) { RB_OBJ_WRITE(lazy, &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.
2181 2182 2183 2184 2185 2186 2187 2188 2189 |
# File 'enumerator.c', line 2181 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]
2215 2216 2217 2218 2219 2220 2221 2222 2223 |
# File 'enumerator.c', line 2215 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.
2181 2182 2183 2184 2185 2186 2187 2188 2189 |
# File 'enumerator.c', line 2181 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}]
2151 2152 2153 2154 2155 2156 2157 2158 2159 |
# File 'enumerator.c', line 2151 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.
2293 2294 2295 2296 2297 2298 2299 |
# File 'enumerator.c', line 2293 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.
2340 2341 2342 2343 2344 2345 2346 |
# File 'enumerator.c', line 2340 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.
2852 2853 2854 2855 2856 |
# File 'enumerator.c', line 2852 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]
2066 2067 2068 2069 2070 2071 2072 2073 2074 |
# File 'enumerator.c', line 2066 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.
2244 2245 2246 2247 2248 2249 2250 2251 2252 |
# File 'enumerator.c', line 2244 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.
2181 2182 2183 2184 2185 2186 2187 2188 2189 |
# File 'enumerator.c', line 2181 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.
2839 2840 2841 2842 2843 |
# File 'enumerator.c', line 2839 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.
2839 2840 2841 2842 2843 |
# File 'enumerator.c', line 2839 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.
2839 2840 2841 2842 2843 |
# File 'enumerator.c', line 2839 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.
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 |
# File 'enumerator.c', line 2494 static VALUE lazy_take(VALUE obj, VALUE n) { long len = NUM2LONG(n); if (len < 0) { rb_raise(rb_eArgError, "attempt to take negative size"); } n = LONG2NUM(len); /* no more conversion */ return lazy_add_method(obj, 0, 0, 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.
2530 2531 2532 2533 2534 2535 2536 2537 2538 |
# File 'enumerator.c', line 2530 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.
1833 1834 1835 1836 |
# File 'enumerator.c', line 1833 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]
1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 |
# File 'enumerator.c', line 1974 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()) { RB_OBJ_WRITE(lazy, &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.
2683 2684 2685 2686 2687 2688 2689 |
# File 'enumerator.c', line 2683 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, returns a lazy enumerator that will iterate over 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.
2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 |
# File 'enumerator.c', line 2767 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.
2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 |
# File 'enumerator.c', line 2419 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); } |