Skip to content

Instantly share code, notes, and snippets.

@havenwood
Created May 7, 2020 15:57
Show Gist options
  • Select an option

  • Save havenwood/58838bbcc5e463b0c3594b16953aa022 to your computer and use it in GitHub Desktop.

Select an option

Save havenwood/58838bbcc5e463b0c3594b16953aa022 to your computer and use it in GitHub Desktop.
A memoized enumerator
# frozen_string_literal: true
class Enumerator
class Memoized < Enumerator
INTERRUPT = defined?(IRB::Abort) ? IRB::Abort : Interrupt
private_constant :INTERRUPT
module Refinement
refine Enumerable do
def memoized
Enumerator::Memoized.new(self)
end
end
end
def initialize(enum)
@enum = case enum
when Enumerator::ArithmeticSequence
Range.new(enum.begin, enum.end, enum.exclude_end?) % enum.step
when Enumerator
enum.clone.rewind
else
enum.clone.each
end
@memoized_values = []
super(@enum.size) do |yielder|
@memoized_values.each do |memoized_value|
yielder << memoized_value
end
loop do
@enum.next.tap do |next_value|
@memoized_values << next_value
yielder << next_value
end
end
rescue INTERRUPT
rewind
raise
end
end
def rewind
@memoized_values.clear
@enum.rewind
super
end
alias eager itself
end
end
using Enumerator::Memoized::Refinement
counter = 1.step.lazy.map { |n| puts "Eagerly producing: #{n} ..."; sleep 1; n }.memoized
p counter.first(2)
p counter.first(2)
p counter.first(3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment