Last active
August 29, 2015 14:10
-
-
Save isaiah/3ae573bdfeb75bdd5788 to your computer and use it in GitHub Desktop.
Pure ruby implementation of lazy enumerator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Enumerator | |
class Lazy | |
def initialize(coll) | |
@lazy = Yid.new do |yielder| | |
if block_given? | |
coll.each do |x| | |
yield yielder, x | |
end | |
else | |
coll.each do |x| | |
yielder.yield x | |
end | |
end | |
end | |
end | |
def each | |
loop { yield @lazy.next } | |
rescue StopIteration | |
end | |
def select | |
Lazy.new(self) do |yielder, *vals| | |
result = yield(*vals) | |
yielder.yield(*vals) if result | |
end | |
end | |
def map | |
Lazy.new(self) do |yielder, *vals| | |
yielder.yield yield(*vals) | |
end | |
end | |
def take(n) | |
i = 0 | |
Lazy.new(self) do |yielder, *vals| | |
if i < n | |
i += 1 | |
yielder.yield(*vals) | |
else | |
raise StopIteration | |
end | |
end | |
end | |
def drop(n) | |
i = 0 | |
Lazy.new(self) do |yielder, *vals| | |
if i < n | |
i += 1 | |
else | |
yielder.yield(*vals) | |
end | |
end | |
end | |
def drop_while | |
to_drop = true | |
Lazy.new(self) do |yielder, *vals| | |
if to_drop | |
result = yield(*vals) | |
if !result | |
to_drop = false | |
end | |
end | |
if !to_drop | |
yielder.yield(*vals) | |
end | |
end | |
end | |
def next | |
@lazy.next | |
end | |
def force | |
ret = [] | |
while val = @lazy.next | |
ret << val | |
end | |
rescue StopIteration | |
ret | |
end | |
private | |
# kudos http://stackoverflow.com/a/19660333/482757 | |
class Yid | |
def initialize(&block) | |
# creates a new Fiber to be used as an Yielder | |
@yielder = Fiber.new do | |
yield Fiber | |
raise StopIteration # raise an error if there is no more calls | |
end | |
end | |
def next | |
# return the value and wait until the next call | |
@yielder.resume | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment