What's the best way to return an Enumerator::Lazy when your class doesn't define #each?

前端 未结 1 1249
陌清茗
陌清茗 2021-01-05 18:29

Enumerable#lazy relies on your enumerable providing an #each method. If your enumerable doesn\'t have an #each method you can\'t use <

相关标签:
1条回答
  • 2021-01-05 18:43

    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.

    0 讨论(0)
提交回复
热议问题