Ruby Lazy Enumerable flat_map不是很懒惰

时间:2014-12-09 16:57:50

标签: ruby lazy-evaluation enumerable

编辑:由于我用错误的例子写了这个问题并没有描述我的问题,我会再做一次!

在我看来,即使是Enumerator :: Lazy类的一部分,#flat_map本身也不是很可枚举的。

此示例正确有效:

(1..Float::INFINITY).flat_map { |s| [s,s] }.take(4).to_a

懒惰的实现也会起作用:

(1..Float::INFINITY).flat_map { |s| [s,s] }.take(4).to_a

这只会考虑到块内生成的数组是有限的。但是在take(4)调用发生之前,它们也将被完全评估。哪个不是很懒惰。

因此,这将失败:

(1..Float::INFINITY).lazy.flat_map { |i| (i..Float::INFINITY).map(&:to_i) }.take(4).force

因为数组"无穷大范围"将在懒惰呼叫发生之前进行全面评估。我希望它默认为#34;懒惰"但是。我的意思是,我确实理解这个难题在哪里,但我希望它以这种方式发生:flat_map评估每个实例是懒惰的,知道结果将是一个数组(或者至少是可枚举的),并将应用懒惰的机制。因此,(i..Float :: INFINITY).map(& to_i)会被放大(这看起来并不兼容,因为地图(&:to_i)调用将会强制"强制&#34 34;要计算)。

1 个答案:

答案 0 :(得分:6)

您实际上并没有使用惰性枚举器。要将普通枚举器转换为惰性枚举器,请使用Enumerable#lazy方法。为了得到结果,我建议使用方法Enumerable::Lazy#force而不是to_a,因为我认为它更清楚地表明了意图。

(1..Float::INFINITY).lazy.flat_map { |s| [s,s] }.take(4).force
#=> [1, 1, 2, 2]