TLDR

The following makes sense for memoizing concrete computed values like arrays:

def foo
  @foo ||= costly_computation
end

But for enumerators it doesn't work, so instead we do this:

def foo
  costly_computation_enumerator.memoizing.lazy
end

enumerator-memoizing

This gem provides a Ruby implementation of the memoization pattern commonly found in functional programming languages. Memoization is used to save computation time by saving computed values in memory. When used in combination with enumerable-lazy you can use lazy for deferring the computation until the elements are accessed and memoizing to allow accessing already computed values without the need to compute them again.

Example

The following example makes use of lazy enumerables for computing prime numbers using an infinite list, first without and then with memoizing.

require 'enumerable/lazy'
require 'enumeration/memoizing'
require 'prime'
INFINITY = 1.0 / 0

all_primes = (1..INFINITY).lazy.map{|n| n**2+1}.select{|m| m.prime?}

# Test all the numbers from 1 to 28238597 -> first 500 primes
all_primes.first(500)

# Test all the numbers from 1 to 147379601 -> first 1000 primes
all_primes.first(1000)


memoizing_primes = all_primes.memoizing

# Test all the numbers from 1 to 28238597 (Memoizing the computed results) -> first 500 primes
memoizing_primes.first(500) 

# Don't check 1 to 28238597 (they are memoized), Then test all the numbers from 282385978 to 147379601 -> first 1000 primes
memoizing_primes.first(1000) 

# Return the memoized list of primes from 1 to 147379601, not doing any computation at all -> first 1000 primes
memoizing_primes.first(1000)