Class: Enumerator::Lazy
- Inherits:
-
Enumerator
- Object
- Enumerator
- Enumerator::Lazy
- Defined in:
- mrbgems/mruby-enum-lazy/mrblib/lazy.rb
Overview
Acknowledgements
Based on https://github.com/yhara/enumerable-lazy
Inspired by https://github.com/antimon2/enumerable_lz
http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja)
Instance Method Summary collapse
-
#drop(n) ⇒ Object
call-seq: lazy.drop(n) -> lazy_enumerator.
-
#drop_while(&block) ⇒ Object
call-seq: lazy.drop_while {|obj| block } -> lazy_enumerator.
-
#flat_map(&block) ⇒ Object
(also: #collect_concat)
call-seq: lazy.flat_map {|obj| block } -> lazy_enumerator lazy.collect_concat {|obj| block } -> lazy_enumerator.
-
#grep(pattern) ⇒ Object
call-seq: lazy.grep(pattern) -> lazy_enumerator.
-
#grep_v(pattern) ⇒ Object
call-seq: lazy.grep_v(pattern) -> lazy_enumerator.
-
#initialize(obj, &block) ⇒ Lazy
constructor
call-seq: Lazy.new(obj, &block).
-
#map(&block) ⇒ Object
(also: #collect)
call-seq: lazy.map {|obj| block } -> lazy_enumerator lazy.collect {|obj| block } -> lazy_enumerator.
-
#reject(&block) ⇒ Object
call-seq: lazy.reject {|obj| block } -> lazy_enumerator.
-
#select(&block) ⇒ Object
(also: #find_all)
call-seq: lazy.select {|obj| block } -> lazy_enumerator lazy.find_all {|obj| block } -> lazy_enumerator.
-
#take(n) ⇒ Object
call-seq: lazy.take(n) -> lazy_enumerator.
-
#take_while(&block) ⇒ Object
call-seq: lazy.take_while {|obj| block } -> lazy_enumerator.
-
#to_enum(meth = :each, *args, &block) ⇒ Object
(also: #enum_for)
call-seq: lazy.to_enum(method = :each, *args) -> lazy_enum lazy.to_enum(method = :each, *args) {|*args| ... } -> lazy_enum lazy.enum_for(method = :each, *args) -> lazy_enum lazy.enum_for(method = :each, *args) {|*args| ... } -> lazy_enum.
-
#uniq(&block) ⇒ Object
call-seq: lazy.uniq -> lazy_enumerator lazy.uniq {|item| block } -> lazy_enumerator.
-
#zip(*args, &block) ⇒ Object
call-seq: lazy.zip(arg, ...) -> lazy_enumerator lazy.zip(arg, ...) {|arr| block } -> lazy_enumerator.
Constructor Details
#initialize(obj, &block) ⇒ Lazy
call-seq:
Lazy.new(obj, &block)
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 by calling yielder.yield. For example, to create a method that acts like Array#select:
def select
Lazy.new(self) do |yielder, value|
yielder.yield(value) if yield(value)
end
end
59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 59 def initialize(obj, &block) super(){|yielder| begin obj.each {|x| if block block.call(yielder, x) else yielder << x end } rescue StopIteration end } end |
Instance Method Details
#drop(n) ⇒ Object
call-seq:
lazy.drop(n) -> lazy_enumerator
Like Enumerable#drop, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.drop(3).first(3)
#=> [4, 5, 6]
206 207 208 209 210 211 212 213 214 215 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 206 def drop(n) dropped = 0 Lazy.new(self){|yielder, val| if dropped < n dropped += 1 else yielder << val end } end |
#drop_while(&block) ⇒ Object
call-seq:
lazy.drop_while {|obj| block } -> lazy_enumerator
Like Enumerable#drop_while, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.drop_while {|i| i < 4 }.first(3)
#=> [4, 5, 6]
226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 226 def drop_while(&block) dropping = true Lazy.new(self){|yielder, val| if dropping if not block.call(val) yielder << val dropping = false end else yielder << val end } end |
#flat_map(&block) ⇒ Object Also known as: collect_concat
call-seq:
lazy.flat_map {|obj| block } -> lazy_enumerator
lazy.collect_concat {|obj| block } -> lazy_enumerator
Like Enumerable#flat_map, but chains operation to be lazy-evaluated.
["foo", "bar"].lazy.flat_map {|i| i.each_char.lazy}.force
#=> ["f", "o", "o", "b", "a", "r"]
292 293 294 295 296 297 298 299 300 301 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 292 def flat_map(&block) Lazy.new(self){|yielder, val| result = block.call(val) if result.respond_to?(:each) result.each {|x| yielder << x } else yielder << result end } end |
#grep(pattern) ⇒ Object
call-seq:
lazy.grep(pattern) -> lazy_enumerator
Like Enumerable#grep, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.grep(1..10).force
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
172 173 174 175 176 177 178 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 172 def grep(pattern) Lazy.new(self){|yielder, val| if pattern === val yielder << val end } end |
#grep_v(pattern) ⇒ Object
call-seq:
lazy.grep_v(pattern) -> lazy_enumerator
Like Enumerable#grep_v, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.grep_v(2..4).first(3)
#=> [1, 5, 6]
189 190 191 192 193 194 195 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 189 def grep_v(pattern) Lazy.new(self){|yielder, val| unless pattern === val yielder << val end } end |
#map(&block) ⇒ Object Also known as: collect
call-seq:
lazy.map {|obj| block } -> lazy_enumerator
lazy.collect {|obj| block } -> lazy_enumerator
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]
120 121 122 123 124 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 120 def map(&block) Lazy.new(self){|yielder, val| yielder << block.call(val) } end |
#reject(&block) ⇒ Object
call-seq:
lazy.reject {|obj| block } -> lazy_enumerator
Like Enumerable#reject, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.reject {|i| i.even? }.first(3)
#=> [1, 3, 5]
155 156 157 158 159 160 161 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 155 def reject(&block) Lazy.new(self){|yielder, val| unless block.call(val) yielder << val end } end |
#select(&block) ⇒ Object Also known as: find_all
call-seq:
lazy.select {|obj| block } -> lazy_enumerator
lazy.find_all {|obj| block } -> lazy_enumerator
Like Enumerable#select, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.select {|i| i.even? }.first(3)
#=> [2, 4, 6]
137 138 139 140 141 142 143 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 137 def select(&block) Lazy.new(self){|yielder, val| if block.call(val) yielder << val end } end |
#take(n) ⇒ Object
call-seq:
lazy.take(n) -> lazy_enumerator
Like Enumerable#take, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.take(3).force
#=> [1, 2, 3]
249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 249 def take(n) if n == 0 return Lazy.new(self){raise StopIteration} end taken = 0 Lazy.new(self){|yielder, val| yielder << val taken += 1 if taken >= n raise StopIteration end } end |
#take_while(&block) ⇒ Object
call-seq:
lazy.take_while {|obj| block } -> lazy_enumerator
Like Enumerable#take_while, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.take_while {|i| i < 4 }.force
#=> [1, 2, 3]
272 273 274 275 276 277 278 279 280 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 272 def take_while(&block) Lazy.new(self){|yielder, val| if block.call(val) yielder << val else raise StopIteration end } end |
#to_enum(meth = :each, *args, &block) ⇒ Object Also known as: enum_for
call-seq:
lazy.to_enum(method = :each, *args) -> lazy_enum
lazy.to_enum(method = :each, *args) {|*args| ... } -> lazy_enum
lazy.enum_for(method = :each, *args) -> lazy_enum
lazy.enum_for(method = :each, *args) {|*args| ... } -> lazy_enum
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 on a lazy enumerator.
For example:
module Enumerable
def filter_map(&block)
map(&block).compact
end
end
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 93 def to_enum(meth=:each, *args, &block) unless self.respond_to?(meth) raise ArgumentError, "undefined method #{meth}" end lz = Lazy.new(self, &block) obj = self lz.instance_eval { @obj = obj @meth = meth @args = args } lz end |
#uniq(&block) ⇒ Object
call-seq:
lazy.uniq -> lazy_enumerator
lazy.uniq {|item| block } -> lazy_enumerator
Like Enumerable#uniq, but chains operation to be lazy-evaluated.
(1..Float::INFINITY).lazy.map {|i| i % 3}.uniq.first(3)
#=> [1, 2, 0]
337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 337 def uniq(&block) hash = {} Lazy.new(self){|yielder, val| if block v = block.call(val) else v = val end unless hash.include?(v) yielder << val hash[v] = val end } end |
#zip(*args, &block) ⇒ Object
call-seq:
lazy.zip(arg, ...) -> lazy_enumerator
lazy.zip(arg, ...) {|arr| block } -> lazy_enumerator
Like Enumerable#zip, but chains operation to be lazy-evaluated. However, if a block is given to zip, values are enumerated immediately.
(1..Float::INFINITY).lazy.zip(('a'..'z').cycle).first(3)
#=> [[1, "a"], [2, "b"], [3, "c"]]
315 316 317 318 319 320 321 322 323 324 325 |
# File 'mrbgems/mruby-enum-lazy/mrblib/lazy.rb', line 315 def zip(*args, &block) enums = [self] + args Lazy.new(self){|yielder, val| ary = enums.map {|e| e.next} if block yielder << block.call(ary) else yielder << ary end } end |