加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 当你的类没有定义#each时,返回Enumerator :: Lazy的最佳

发布时间:2020-12-17 03:31:06 所属栏目:百科 来源:网络整理
导读:可枚举#lazy依赖于你的可枚举提供#each方法.如果您的枚举没有#each方法,则无法使用#lazy.现在,内核#enum_for和#to_enum可以灵活地指定除#each之外的枚举方法: Kernel#enum_for(method = :each,*args) 但#enum_for和朋友总是构造普通(非懒惰)枚举器,而不是En
可枚举#lazy依赖于你的可枚举提供#each方法.如果您的枚举没有#each方法,则无法使用#lazy.现在,内核#enum_for和#to_enum可以灵活地指定除#each之外的枚举方法:

Kernel#enum_for(method = :each,*args)

但#enum_for和朋友总是构造普通(非懒惰)枚举器,而不是Enumerator :: Lazy.

我看到Ruby 1.9.3中的Enumerator提供了类似的#new形式:

Enumerator#new(obj,method = :each,*args)

不幸的是,在Ruby 2.0中已经完全删除了构造函数.此外,我认为它在Enumerator :: Lazy上根本不可用.所以在我看来,如果我有一个带有方法的类,我想返回一个惰性枚举器,如果该类没有#each,那么我必须定义一些定义#each的辅助类.

例如,我有一个Calendar类.从一开始就提出列举每一个日期对我来说真的没有意义. #each会没用.相反,我提供了一个从开始日期(懒惰)枚举的方法:

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

并且EachFrom类看起来像这样:

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

它有效,但感觉很重.也许我应该继承Enumerator :: Lazy并定义一个类似于Enumerator中弃用的构造函数.你怎么看?

解决方法

我认为你应该使用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

这是大多数ruby家所期望的.即使它是无限的Enumerable,它仍然可用,例如:

Calendar.new.each_from(1.year.from_now).first(10) # => [...first ten dates...]

如果他们确实需要一个懒惰的枚举器,他们可以自己调用懒人:

Calendar.new.each_from(1.year.from_now)
  .lazy
  .map{...}
  .take_while{...}

如果你真的想要返回一个懒惰的枚举器,你可以从你的方法调用lazy:

# ...
  def each_from(first)
    return to_enum(:each_from,first).lazy unless block_given?
    #...

我不会推荐它,因为它会出乎意料(IMO),可能是一种矫枉过正,而且效率会降低.

最后,你的问题中存在一些误解:

> Enumerable的所有方法都假定每个,而不仅仅是懒惰.>如果您愿意,可以定义需要参数的每个方法,并包含Enumerable. Enumerable的大多数方法都不起作用,但each_with_index和其他几个方法将转发参数,以便这些方法可以立即使用.>没有块的Enumerator.new已经消失,因为to_enum是应该使用的.请注意,块形式仍然存在.还有一个Lazy的构造函数,但它的意思是从现有的Enumerable开始.>你声明to_enum永远不会创建一个懒惰的枚举器,但这并不完全正确. Enumerator :: Lazy#to_enum专门用于返回一个惰性枚举器. Enumerable上调用to_enum的任何用户方法都会使懒惰的枚举器保持惰性.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读