ruby – 当你的类没有定义#each时,返回Enumerator :: Lazy的最佳
可枚举#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的任何用户方法都会使懒惰的枚举器保持惰性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |