Skip to content

Instantly share code, notes, and snippets.

@sionide21
Last active August 29, 2015 14:10
Show Gist options
  • Save sionide21/531f3bb3d77b5061fa0c to your computer and use it in GitHub Desktop.
Save sionide21/531f3bb3d77b5061fa0c to your computer and use it in GitHub Desktop.
Lazy enumerators aren't magic
class Benerator
def initialize(&block)
@block = block
end
def next
as_array.shift
end
def as_array
# Load the output of the generator into memory, #next simply reads from the array
@as_array ||= [].tap { |a| @block.call(->(x){a << x }) }
end
end
enum = Benerator.new do |y|
y.yield :hello
y.yield :world
end
puts "First: #{enum.next}"
puts "Second: #{enum.next}"
require 'fiber'
class LazyBenerator
def initialize(&block)
@block = block
end
def next
fiber.resume
end
def fiber
# Create a fiber that returns each successive yield when #next is called
@fiber ||= Fiber.new do
@block.call(->(x) {
Fiber.yield x
})
end
end
end
enum = LazyBenerator.new do |y|
y.yield :hello
y.yield :world
end
puts "First: #{enum.next}"
puts "Second: #{enum.next}"
fib = LazyBenerator.new do |yielder|
x, y = 1, 1
loop do
yielder.yield x
x, y = y, x + y
end
end
10.times do
puts fib.next
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment