diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2014-04-04 10:33:17 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2014-04-04 10:33:17 +0900 |
| commit | 7a9630a5bb9534ab266aa225d728935ad648b861 (patch) | |
| tree | 9c25558f3b4369461e4fd1a6a5c78452c918d2f5 /mrbgems/mruby-enum-lazy/mrblib | |
| parent | 4e5ec1993adb7f156edb08b9077734f8f9ef8b48 (diff) | |
| download | mruby-7a9630a5bb9534ab266aa225d728935ad648b861.tar.gz mruby-7a9630a5bb9534ab266aa225d728935ad648b861.zip | |
add mruby-enum-lazy mrbgem for Enumerable::Lazy
Diffstat (limited to 'mrbgems/mruby-enum-lazy/mrblib')
| -rw-r--r-- | mrbgems/mruby-enum-lazy/mrblib/lazy.rb | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb new file mode 100644 index 000000000..088ce760d --- /dev/null +++ b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb @@ -0,0 +1,150 @@ +# = Enumerable#lazy implementation +# +# Enumerable#lazy returns an instance of Enumerable::Lazy. +# You can use it just like as normal Enumerable object, +# except these methods act as 'lazy': +# +# - map collect +# - select find_all +# - reject +# - grep +# - drop +# - drop_while +# - take_while +# - flat_map collect_concat +# - zip +# +# == 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) + +module Enumerable + def lazy + Lazy.new(self) + end + + class Lazy < Enumerator + def initialize(obj, &block) + super(){|yielder| + begin + obj.each{|x| + if block + block.call(yielder, x) + else + yielder << x + end + } + rescue StopIteration + end + } + end + + def map(&block) + Lazy.new(self){|yielder, val| + yielder << block.call(val) + } + end + alias collect map + + def select(&block) + Lazy.new(self){|yielder, val| + if block.call(val) + yielder << val + end + } + end + alias find_all select + + def reject(&block) + Lazy.new(self){|yielder, val| + if not block.call(val) + yielder << val + end + } + end + + def grep(pattern) + Lazy.new(self){|yielder, val| + if pattern === val + yielder << val + end + } + end + + def drop(n) + dropped = 0 + Lazy.new(self){|yielder, val| + if dropped < n + dropped += 1 + else + yielder << val + end + } + end + + 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 + + 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 + + def take_while(&block) + Lazy.new(self){|yielder, val| + if block.call(val) + yielder << val + else + raise StopIteration + end + } + end + + def flat_map(&block) + Lazy.new(self){|yielder, val| + ary = block.call(val) + # TODO: check ary is an Array + ary.each{|x| + yielder << x + } + } + end + alias collect_concat flat_map + + 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 + + alias force to_a + end +end |
