I’m trying to cache a lazy-evaluated, param-based Enumerator calls.
Considering the following code:
def arith a, b
Enumerator.new do |yielder|
[‘+’, ‘*’].each do |oper|
sleep 1 # simulates a param-based, long-running process
yielder.yield [oper, eval(“#{a} #{oper} #{b}”)]
end
end
end
[[1,2], [3,4], [5,6], [1,2], [3,4], [5,6], [7,8]].each do |a, b|
arith(a,b).each do |oper, result|
puts “#{a} #{oper} #{b} = #{result}”
end
end
should take about 14 seconds to run, with arith() lazily returning the
sum and product of its params. Still, if you look closely, arith(1,2),
arith(3,4) and arith(5,6) are called twice; if there was caching of
the yielded values there would be no need to recompute these sums
and products (and the whole process would take around eight seconds
instead).
I’m still rather new to Enumerators, but in my project their lazy
evaluation is an amazing benefit. What’s the best/simplest way to
introduce caching in the above scenario?
(Ideally, I’d love to have the caching done outside the Enumerator,
as in my project’s case the arith() method is provided by various
interchangeable modules¹, but if it’s only – or much easier – doable
from inside the Enumerator then so be it, I’ll add it in every
implementation…)
¹
– ignoring that #decompositions is itself an Enumerator, what I want is
for qv_gen to not recompute blankets if qv_gen.blankets(fsm, u, v, qu)
was already called previously with the same params
Thanks in advance for any insight in how to solve this problem!
— Shot