Enumerable#lazy relies on your enumerable providing an #each method. If your enumerable doesn\'t have an #each method you can\'t use <
I think you should return a normal Enumerator using to_enum:
class Calendar
# ...
def each_from(first)
return to_enum(:each_from, first) unless block_given?
loop do
yield first if include?(first)
first += step
end
end
end
This is what most rubyists would expect. Even though it's an infinite Enumerable, it is still usable, for example:
Calendar.new.each_from(1.year.from_now).first(10) # => [...first ten dates...]
If they actually need a lazy enumerator, they can call lazy themselves:
Calendar.new.each_from(1.year.from_now)
.lazy
.map{...}
.take_while{...}
If you really want to return a lazy enumerator, you can call lazy from you method:
# ...
def each_from(first)
return to_enum(:each_from, first).lazy unless block_given?
#...
I would not recommend it though, since it would be unexpected (IMO), could be an overkill and will be less performant.
Finally, there are a couple of misconceptions in your question:
All methods of Enumerable assume an each, not just lazy.
You can define an each method that requires a parameter if you like and include Enumerable. Most methods of Enumerable won't work, but each_with_index and a couple of others will forward arguments so these would be usable immediately.
The Enumerator.new without a block is gone because to_enum is what one should use. Note that the block form remains. There's also a constructor for Lazy, but it's meant to start from an existing Enumerable.
You state that to_enum never creates a lazy enumerator, but that's not entirely true. Enumerator::Lazy#to_enum is specialized to return a lazy enumerator. Any user method on Enumerable that calls to_enum will keep a lazy enumerator lazy.