Ruby on rails 基于Ruby枚举器的延迟展平方法
Michael Harrison在上发表了一篇很好的文章,提供了Ruby on rails 基于Ruby枚举器的延迟展平方法,ruby-on-rails,ruby,functional-programming,lazy-evaluation,enumerator,Ruby On Rails,Ruby,Functional Programming,Lazy Evaluation,Enumerator,Michael Harrison在上发表了一篇很好的文章,提供了lazy\u select和lazy\u map的实现。我想知道lazy_flant的以下实现是否应该对枚举器和可枚举类型以外的任何类型进行特殊处理 class Enumerator def lazy_flatten Enumerator.new do |yielder| self.each do |value| if value.kind_of? Enumerator
lazy\u select
和lazy\u map
的实现。我想知道lazy_flant
的以下实现是否应该对枚举器和可枚举类型以外的任何类型进行特殊处理
class Enumerator
def lazy_flatten
Enumerator.new do |yielder|
self.each do |value|
if value.kind_of? Enumerator
value.lazy_flatten.each do |v|
yielder.yield v
end
elsif value.kind_of? Enumerable
value.flatten.each do |v|
yielder.yield v
end
else
yielder.yield value
end
end
end
end
end
在我看来,这并不懒惰,因为您仍然在下面执行旧的(非懒惰的)flatten
枚举器
是可枚举的
,因此我认为您不需要单独处理它
我希望lazy\u flant
是Enumerable
上的方法
以下是我将如何实施它:
module Enumerable
def lazy_flatten
Enumerator.new do |yielder|
each do |element|
if element.is_a? Enumerable
element.lazy_flatten.each do |e|
yielder.yield(e)
end
else
yielder.yield(element)
end
end
end
end
end
注意,在Ruby 2.0+中,您不需要这样做,只需使用,它返回一个
出于我不清楚的原因,Lazy
没有flatten
,但它有,所以原则上你可以使用flatte\u map
模块可枚举
def lazy_展平
self.lazy.flat_映射{| x | x}
结束
结束
Lazy#flat_map
主要负责分解任何可分解元素,但不完全是从以下方面:
如果以下任一条件为真,则分解块返回的值x:
x同时响应每个
和强制
,这意味着x
是一个惰性枚举器
x是一个数组或响应到_ary
请注意,到_ary
不是可枚举的方法,可能是为了阻止从无限序列到数组。这意味着,例如,如果您试图用上述代码展平包含集合
或范围
的对象,则它(arguaby,见下文)将不起作用:
a=[[1,2,3],Set[4,5],6,7..8]
# => [[1, 2, 3], #, 6, 7..8]
f=a.lazy\u展平
# => #
f、 到
# => [1, 2, 3, #, 6, 7..8]
但是,这与数组#展平
的行为相同:
a.flatten
# => [1, 2, 3, #, 6, 7..8]
(虽然Array#flant
不会检测和分解惰性枚举数,lazy#flat(map
会检测和分解惰性枚举数。)
而OP的代码或中的代码将分解集合
和范围
:
f=a.lazy\u flatten(M.J.的代码)
# => #
f、 到
# => [1, 2, 3, 4, 5, 6, 7, 8]
但是,如果传递包含无限序列的内容,该代码也将无限迭代:
a=[[1,2,3],Set[4,5],6,7..8,9..Float::INFINITY]
#=>[[1,2,3],#,6,7..8,9..无穷大]
f=a.lazy_flatten(M.J.的代码)
# => #
f、 到
#=>在100%CPU下旋转一段时间,最终耗尽内存
如果你认为这是一个特性,而不是一个bug,那么一种方法是修改<代码>平面地图> /COD>基础实现,将它找到的任何枚举都转换成懒惰的:
模块可枚举
def lazy_展平
self.lazy.flat|map do|x|
x、 对(懒惰)有反应吗?x、 懒惰:x
结束
结束
结束
这甚至适用于嵌套的惰性枚举,因为lazy#lazy
足够聪明,可以返回自身