Stream类的原因可用于“一流”循环'

时间:2015-09-07 07:50:01

标签: scala

Stream(1,2,3,4).map(_+10).filter(_%2==0).toList

我很好奇为什么上面的表达式应该由一个元素逐个元素执行而没有临时输出(第一类循环)。例如,

cons(11, Stream(2,3,4).map(_+10)).filter(_%2==0).toList
cons(12, Stream(3,4).map(_+10)).filter(_%2==0).toList
12 :: cons(13, Stream(4).map(_+10)).filter(_%2==0).toList
12 :: 14 :: List()

由于没有额外的命令来改变执行顺序。 我认为执行顺序会喜欢这个,

cons(11, Stream(2,3,4).map(_+10)).filter(_%2==0).toList
cons(11, cons(12, Stream(3,4).map(_+10))).filter(_%2==0).toList
cons(11, cons(12, cons(13, Stream(4).map(_+10)))).filter(_%2==0).toList
cons(11, cons(12, cons(13, cons(14, Empty))))).filter(_%2==0).toList
.
.
12 :: 14 :: List()

因为map命令比filter命令更好。

......在我写这篇文章时,我意识到可能还有另一条规则:

'外部命令首先,内部命令后来'

这个'外部 - >内'规则比“左”更快 - >右'规则。 所以,下面的内部地图命令比下面的外部过滤命令慢。

cons(11, Stream(2,3,4).map(_+10)).filter(_%2==0).toList

我的想法是对的吗?

1 个答案:

答案 0 :(得分:2)

因为流是惰性的,所以每个元素都在“根据需要”的基础上进行评估。请考虑以下示例流:

val es = Stream(2,3,4).map(x=>{println("add");x+10})
                      .filter(x=>{println("filt");x%2==0})

第一个元素是使用流的定义进行评估的,但除非你要求它,否则没有别的。

scala> es(0)
res314: Int = 12

scala> es(1)
add
filt
add
filt
res315: Int = 14

这样想,当我要求es(1)它“拉”3通过map(添加10)但它无法通过filter。由于我们仍然没有下一个es()元素,因此我们不得不在map中拉4,这次它通过了filter步骤。