Enumerable#lazy
relies on your enumerable providing an #each
method. If your enumerable doesn't have an #each
method you can't use #lazy
. Now Kernel#enum_for
and #to_enum
provide the flexibility to specify an enumeration method other than #each
:
Kernel#enum_for(method = :each, *args)
But #enum_for
and friends always construct plain (non-lazy) enumerators, never Enumerator::Lazy
.
I see that Enumerator
in Ruby 1.9.3 offers this similar form of #new:
Enumerator#new(obj, method = :each, *args)
Unfortunately that constructor has been completely removed in Ruby 2.0. Also I don't think it was ever available at all on Enumerator::Lazy
. So it seems to me that if I have a class with a method I want to return a lazy enumerator for, if that class has no #each
then I have to define some helper class that does define #each
.
For instance, I've got a Calendar
class. It doesn't really make sense for me to offer to enumerate every date from the beginning of all time. An #each
would be useless. Instead I offer a method that enumerates (lazily) from a starting date:
class Calendar
...
def each_from(first)
if block_given?
loop do
yield first if include?(first)
first += step
end
else
EachFrom.new(self, first).lazy
end
end
end
And that EachFrom
class looks like this:
class EachFrom
include Enumerable
def initialize(cal, first)
@cal = cal
@first = first
end
def each
@cal.each_from(@first) do |yielder, *vals|
yield yielder, *vals
end
end
end
It works but it feels heavy. Maybe I should subclass Enumerator::Lazy
and define a constructor like that deprecated one from Enumerator
. What do you think?